/*----------------------------------------------------------------* |srtp_proto.h | |@version: 2.1 | |Last Modification: Oct 1st, 2003 , by Fei, based on 06170301 | | | | Define SRMP constants, data structures and function prototypes | *----------------------------------------------------------------*/ /*----------------------------------------------------------------* | Copyright 2001-2003 Networking and Simulation Laboratory | | George Mason University, Fairfax, Virginia | | | | Permission to use, copy, modify, and distribute this | | software and its documentation for academic purposes is hereby | | granted without fee, provided that the above copyright notice | | and this permission appear in all copies and in supporting | | documentation, and that the name of George Mason University | | not be used in advertising or publicity pertaining to | | distribution of the software without specific, written prior | | permission. GMU makes no representations about the suitability | | of this software for any purposes. It is provided "AS IS" | | without express or implied warranties. All risk associated | | with use of this software is expressly assumed by the user. | *----------------------------------------------------------------*/ #define SRTP_VERSION 2 #define MAX_SUB_MCA_NUM 20 /* subscribed_mca[], client_port[][] */ #define MAX_CLIENT_PER_MCA 100 /* client_port[][] */ #define MAX_REG_MCA_NUM 200 /* registered , registered_dataid[] */ /* outgoing_bundle_pool[] ... the maximum number of outgoing bundles at the same time */ #define MAX_BUFFERED_OUTGOING_BUNDLE 1000 /* maximum number of un-resembled long m1 messages at the same time */ #define MAX_UNASEMBLED_M1_MESSAGES 10 #define MAX_M1_PER_BUNDLE 10 #define MAX_REQUEST_LEN 131099 /* the max request size from local client */ #define REQ_HEADER_LEN 28 /* the length of the client request header */ #define MAX_DSN_PER_BUNDLE 10 /* the maximum m1 message len specified in the draft */ #define MAX_M1_MESSAGE_LEN 131071 #define MAX_M1_BUFFER_SIZE 131111 /* MAX_M1_MESSAGE_LEN + MESSAGE_HEADER_LEN(40) */ #define MAX_INCOM_MSG_NUM 100 /* incoming_message_pool size */ /* buffer size for packets received from the socket at the receiver side */ #define MAX_INCOMING_PACKETS 1000 /* maximum m1 segment size MAX_M1_SEG_SIZE+M1_HEADER_LEN=MAX_BUNDLE_SIZE */ #define MAX_M1_SEG_SIZE 1468 /* MAX_BUNDLE_SIZE + BUNDLE_HEADER_SIZE(24) =1500 */ #define MAX_BUNDLE_SIZE 1476 #define BUNDLE_HEADER_SIZE 24 #define MAX_SN 511 /* 9bits sn */ /* SRTP request types */ #define SRTP_INIT 0 #define SRTP_TERM 1 #define SRTP_REGDATAID 2 #define SRTP_DROPDATAID 3 #define SRTP_SEND 4 #define SRTP_SUB_MCA 5 #define SRTP_UNSUB_MCA 6 /* SRTP message types */ #define SRTP_M0 0 #define SRTP_M1 1 #define SRTP_NACK 7 /* SRTP message types */ #define SRTP_NAK 7 #define SRTP_ACK 1 #define SRTP_DATA 2 #define SRTP_HBEAT 3 #define M0_HEADER_LEN 4 /* mode 0 header length */ #define M1_HEADER_LEN 8 /* mode 1 header length */ #define MESSAGE_HEADER_LEN 40 /* the length of header used withing SRTP */ /* the message here do NOT mean mode 1 or mode 0 messages * it is the data structure used with message parsing between * threads inside SRTP */ #define NACK_HEADER_LEN 12 /* Note: need to debug, should be 10 */ /* SRTP limits */ #define SRTP_HEADER_LENGTH 26 /* 12+4+2+2+2+4, used in heart beat */ #define EQUAL 0 #define NONE -1 #define LESS_BUT_WITHIN_WINDOW 1 #define WITHIN_WINDOW 2 #define WINDOW 30 #define OLD 101 #define NEW 201 #define BUNDLE_TIMEOUT 15; typedef unsigned char __u8; typedef unsigned short __u16; typedef unsigned int __u32; typedef unsigned long __u64; /* the message header format for client request */ typedef struct request_t { unsigned short int version; unsigned short int type; unsigned long mca; unsigned int dataid; unsigned int len; unsigned short int mode; unsigned int port; unsigned int ack_port; } request_t; /* structure to record each registered dataid, and the mca, mode associated with it */ typedef struct registered_dataid_t { unsigned long int mca; unsigned int dataid; int mode; } registered_dataid_t; /* mode 0 message header */ #ifdef UNIX struct m0_hdr_t { __u8 version: 4, type: 4; __u8 mode: 3, pad1: 5; __u16 len; }; /* mode 1 message header */ struct m1_hdr_t { __u8 version: 4, type: 4; __u8 mode: 3, pad1: 5; __u16 len; __u16 dataid; __u16 sn: 9, nosegs: 7; }; /* NACK message header */ struct nack_hdr_t { __u8 version: 4, type: 4; __u8 mode: 3, pad1: 5; __u16 len; __u16 dataid; __u32 source_ip; }; /* the bundle header for transmission */ struct bundle_hdr_t { __u8 version: 4, type: 4; __u8 fb_nr: 4, reserved: 3, is_clr_flag: 1; __u16 bundle_sn; struct in_addr sender_id; struct in_addr receiver_id; __u16 sender_timestamp; __u16 receiver_timestamp; __u16 x_supp_man: 11, x_supp_exp: 5; __u16 r_max; __u8 dsn_count; __u8 pad; __u16 len; }; #else struct m0_hdr_t { __u8 type: 4, version: 4; __u8 pad1: 5, mode: 3; __u16 len; }; /* mode 1 message header */ struct m1_hdr_t { __u8 type: 4, version: 4; __u8 pad1: 5, mode: 3; __u16 len; __u16 dataid; __u16 sn: 9, nosegs: 7; }; /* NACK message header */ struct nack_hdr_t { __u8 type:4, version:4; __u8 pad1:5, mode:3; __u16 len; __u16 dataid; __u32 source_ip; }; struct bundle_hdr_t { __u8 type: 4, version: 4; __u8 is_clr_flag:1, reserved: 3, fb_nr: 4; __u16 bundle_sn; struct in_addr sender_id; struct in_addr receiver_id; __u16 sender_timestamp; __u16 receiver_timestamp; __u16 x_supp_exp: 5, x_supp_man: 11; __u16 r_max; __u8 dsn_count; __u8 pad; __u16 len; }; #endif /* message header used within SRTP */ struct message_header_t { int version; int mode; int len; int type; unsigned int sn; unsigned int dataid; unsigned long int mca; unsigned long int source_ip; int nosegs; unsigned int port; }; /* structure to buffer outgoing and incoming m1 message*/ /* this is used for retransmit, or send most recent m1 message to new clients */ typedef struct recent_m1_buffer_t { unsigned int dataid; unsigned long mca; unsigned long source_ip; int sn; int refresh; int len; char buffer [MAX_M1_BUFFER_SIZE]; struct recent_m1_buffer_t *next; } recent_m1_buffer_t; /* each outgoing message will be put into a link list of this strucutre */ /* retrieve thread is the producer of the data structure */ /* bundler_thread is the consumer */ typedef struct outgoing_segment_t { char *msg; int length; unsigned long int mca; struct outgoing_segment_t *next; unsigned int dataid; } outgoing_segment_t; /* for buffering outgoing m1 message */ typedef struct message_buffer_t { unsigned int dataid; unsigned long dest_mca; char *message; int length; struct message_buffer_t *next; } message_buffer_t; /* for outgoing bundles, each record may be bundles finisied or unfihished */ struct outgoing_bundle_t { char body[MAX_BUNDLE_SIZE]; unsigned long int mca; int len; int flag; /* 0 - empty, 1 - unfished, 2 - finished */ /* dataid list of mode 1 messages' dataids inside the bundle */ int dataid[MAX_M1_PER_BUNDLE]; }; /* for bundle timeout timer */ typedef struct bundle_timeout_timer_t { long bundle_timeout; unsigned long int mca; int index; int sendflag; struct bundle_timeout_timer_t *next; } bundle_timeout_timer_t; /* reference to outgoing bundles */ typedef struct transmit_index_t { unsigned long int SEL_MULTICAST_ADDRESS; int SEL_INDEX; int SEL_LENGTH; struct transmit_index_t *next; } transmit_index_t; /* DSN */ struct dsn_t { __u16 dataid; __u16 sn: 9, nosegs: 7; }; /* the structure to store m1 message segment */ struct m1_seg_buffer_t { int seg_number; int seg_len; char seg_body[MAX_BUNDLE_SIZE]; struct m1_seg_buffer_t * next; struct m1_seg_buffer_t * prev; }; /* the structure to buffer m1 message segments before all the segments arrived */ struct m1_seg_chain_t { struct message_header_t message_header; int len_received; struct m1_seg_buffer_t * chain_head; struct m1_seg_buffer_t * chain_tail; }; typedef struct heartbeat_buffer_t { int eid; int ttl; int cat; int sn; unsigned long mca; long send_time; struct heartbeat_buffer_t *next; int send_flag; } heartbeat_buffer_t; struct socket_info_t{ int socket_id; unsigned long int mca; }; /***************************************************************************************/ /* Function Prototype */ /***************************************************************************************/ /*******************************/ /* functions called by main() **/ /*******************************/ #ifdef UNIX /* the thread for waiting for request from local client */ void * retrieve_thread(void *mp); /* the thread for bundling outgoing messages */ void * bundler_thread(void *mp); /* the thread for transmitting bundles to remote SRTP daemon */ void * transmitter_thread(void *mp); /* the thread for generating heartbeat signal, in case idle */ void * heartbeater_thread(void *mp); /* the thread for signalling a bundle has timed out and shoud be transmitted */ void * signaller_thread(void *mp); /* the thread for receiving a bundle from remote SRTP daemon */ void * receiver_thread(void *mp); /* the thread for parsing messages from a received bundle */ void * unbundler_thread(void *mp); /* the thread for deliving the received messages to local client */ void * deliver_thread(void *mp); #else /* the thread for waiting for request from local client */ void retrieve_thread(void *mp); /* the thread for bundling outgoing messages */ void bundler_thread(void *mp); /* the thread for transmitting bundles to remote SRTP daemon */ void transmitter_thread(void *mp); /* the thread for generating heartbeat signal, in case idle */ void heartbeater_thread(void *mp); /* the thread for signalling a bundle has timed out and shoud be transmitted */ void signaller_thread(void *mp); /* the thread for receiving a bundle from remote SRTP daemon */ void receiver_thread(void *mp); /* the thread for parsing messages from a received bundle */ void unbundler_thread(void *mp); /* the thread for deliving the received messages to local client */ void deliver_thread(void *mp); #endif /* the signal handler for SIGTERM: close opened files and exit */ void sigterm_handler(int sig); void init_server(); /* create and initiate data structures.*/ unsigned long int get_local_ipaddress(char * local_ip_address_string); void create_udp_socket(unsigned int * socket_id, int port_number); void create_mca_socket(unsigned int * socket_id, unsigned long int mca, int port_number); /************************************************/ /* functions called by thread retrieve_thread() */ /************************************************/ /* receive a requst from local client */ int receive_client_request(char * request_buffer,int * request_len); /* function to serve different kind of client request */ int service_init(struct request_t client_header); int service_subscribe_mca(struct request_t client_header); int service_unsubscribe_mca(struct request_t client_header); int service_reg_dataid(struct request_t client_header); int service_drop_dataid(struct request_t client_header); int service_data(struct request_t, char *); int deliver_to_client(int port, char * msg,struct message_header_t message_header); /* function to create a new socket for a new subscribed multicast group */ unsigned int create_receiver_socket(unsigned long int dest_mca); /* function to serve a message that is going to be transmitted to remote site*/ int send_m0(struct request_t client_header, char *req); int send_m1(struct request_t client_header, char *req); int buffer_outgoing_message_m1(char *mesg, int len,unsigned int dataid, unsigned long dest_mca); int update_sn_outgoing(unsigned int dataid,unsigned long mca); void insert_outgoing_pool(char *msg, int msg_len, unsigned long int mca, unsigned int dataid); void insert_incoming_pool(char *indiv_msg, int len); /****************************************/ /* functions called by bundler_thread() */ /****************************************/ int set_bundle_pos(unsigned long int mca); void schedule_signal(unsigned long int mca,int index); int cancel_signal(unsigned long int mca); void schedule_transmission(int index, unsigned long int mca, int len); /********************************************/ /* functions called by transmitter_thread() */ /********************************************/ int oldest_unrefreshed_outgoing_m1_sn( unsigned long mca, unsigned int *m1_dataid); /******************************************/ /* functions called by unbundler_thread() */ /******************************************/ int most_recent_incoming_m1_sn(struct message_header_t message_header); int send_nak(unsigned int dataid, unsigned long int mca, unsigned long int source_ip); /**************************************/ /* functions called by deliver_thread */ /**************************************/ void service_m0(char *, struct message_header_t); void service_m1(char *, struct message_header_t ,int); void service_nak(struct message_header_t message_header); int deliver_message(char * msg, struct message_header_t message_header); int resend_m1(char * buffered_m1); /* buffered_m1 = message_header + message_body */ int update_recvd_m1_sn(struct message_header_t message_header, char * msgbuf, int buffer_flag); /*******************************************/ /* functions called by heartbeatter_thread */ /*******************************************/ void service_heartbeat(char *msg, int n, int p_eid); void schedule_heartbeat(int eid, unsigned long dest_mca, long send_time ); void cancell_heartbeat(int eid, unsigned long dest_mca);