/* * include this header file to gain access to the fishnet API. you * probably want to start by looking at the API section. */ #ifndef __FISH_H__ #define __FISH_H__ /* some standard includes here so you don't need to do them */ #include #ifndef WIN32 #include #endif #include /*----------------------------------------------------------------------------- * fishnet constants */ /* don't pick a fishnet address larger than this, it won't work! */ #define MAX_NODE_ADDRESS 10000 /* packet size limits. the total packet length must be less than the maximum transmission unit or mtu */ #define PACKET_HEADER_SIZE (sizeof(int)*4) #define PACKET_DATA_SIZE 512 #define MTU 1024 /* the time-to-live or ttl limits the number of hops a packet will take to prevent loops. we will use this in assignment 2 */ #define MAX_TTL 16 /* these are the different kinds of packets that can be sent over the fishnet, where each kind corresponds to a protocol; we will implement them starting with assignment 2 */ /* FISH_PROTCOL_ECHO is a backward-compatible alias for FISH_PROTCOL_ECHO_REQUEST, the latter makes more sense when compared to FISH_PROTCOL_ECHO_RESPONSE */ #define FISH_PROTOCOL_ERROR 0 #define FISH_PROTOCOL_ECHO_REQUEST 1 #define FISH_PROTOCOL_ECHO_RESPONSE 3 #define FISH_PROTOCOL_ECHO FISH_PROTOCOL_ECHO_REQUEST #define FISH_PROTOCOL_ROUTING 4 #define FISH_PROTOCOL_TRANSPORT 5 #define FISH_PROTOCOL_MAX 6 /* upper bound, not a real protocol */ /* levels for use with fish_debug(). during fish api calls, debugging information is sent to stderr. these levels control what debugging information */ #define FISH_DEBUG_NONE 0 #define FISH_DEBUG_TOPOLOGY 6 #define FISH_DEBUG_ALL 7 #define FISH_DEBUG_PARANOID 8 /* limit of routing advertisements in a packet, for assignment 3 */ #define MAX_ADVERTISEMENTS ( PACKET_DATA_SIZE / \ sizeof(struct route_advertisement)) /* Just a renaming of above to make it consistent with description given in assignment 3*/ #define MAXADVERTISEMENTS MAX_ADVERTISEMENTS /* The number of hops distance vector algorithm considers as infinity to discover a loop */ #define INFINITY MAX_TTL /*----------------------------------------------------------------------------- * fishnet structures and datatypes */ /* a generic packet has a common header given below, plus data. depending on the type of packet, there will be further structure to the data, for example if the packet is a transport packet then there will be a transport header too */ struct packet { int src; /* source address */ int dst; /* destination address */ int ttl; /* time-to-live counter */ int protocol; /* from universe of protocols */ char data[PACKET_DATA_SIZE]; /* the rest of the packet */ }; /* upcall registered with fish_recvhook() to receive packets from the * networks. this tells you the arguments that a receive handler must * accept. it doesn't return anything. */ typedef void (*receive_handler)(int link_from, /* neighbor address */ char* frame, /* the entire packet received */ int frame_length); /* how long it was */ /* upcall registered with fish_keybhook(). your keyboard input * handler will take two parameters: *line_of_text*, which does not * include the newline (return) character, but is null-terminated so * that functions like sprintf will work, and *length*, which is the * length of the string, not including the null-termination */ typedef void (*keyboard_handler) (char* line_of_text, int length ); /*----------------------------------------------------------------------------- * fishnet API calls */ /* join network is generally the first function you call, to add your * node to a fishnet. the host and port arguments describe the * fishhead to contact, which is synonmous with the network that you * are joining. you supply your requested node address to this * call. the call will either succeed, in which case you have joined * a fishnet, or will fail, printing an error message and * exiting. there are a variety of possible error messages such as * the address you wanted already being in use, or not being able to * contact a fishhead. if join succeeds, the fishhead tells you who * your neighboring nodes are in the topology. you get this * information (which can change) from get_neighbors. */ extern int fish_joinnetwork(const char* host, /* machine running fishhead */ int port, /* port on which the fishhead sits */ int addr); /* your address, from 1 to MAX_NODE_ADDRESS */ /* getneighbors returns a zero terminated array of the addresses of * your neighboring nodes. you should only read this array, not change * it. you must call get_neighbors every time you need to determine * who your neighbors are, as the answer changes as other nodes join * and leave the overall fishnet. for example, if you are the first * node to join then you will have no neighbors until after a second * node joins. note that changes in your neighbor set will only occur * when your program is sitting inside fish_main(), not at any random * time */ extern const int* fish_getneighbors(void); /* recvhook registers a function that you write to be called at a later time when a packet is received from the network. this is upcall style -- you tell fishnet what function to call when a packet is received, rather than call a function directly to receive a packet. your function will be called when a packet arrives *and* your program is sitting inside the fish_main() function. your function gets the packet, and can do anything it likes with it, but must return control to fish_main() after it is finished, since no further packets will be received until this happens. */ extern void fish_recvhook(receive_handler recvhandler); /* keybhook registers a function that you write to be called at a later time when a line of keyboard input is available. like recvhook, it is an upcall that gets called from inside fish_main(). it can do anything it likes with the input, but must return control to fish_main() before further input will be received. */ extern void fish_keybhook(keyboard_handler keybhandler); /* sendpacket sends a packet to an immediate neighor, given the neighbors address and the packet itself as a character array. it can be called any time after a node has joined a network. note that the set of valid neighbors can change dynamically, and is determined with getneighbors. */ extern int fish_sendpacket(int neighbor, /* address of an immediate neighbor */ void* pkt, /* pointer to the packet */ int len); /* length of the whole packet in bytes */ /* this is the main fishnet function. your program will typically join a fishnet, set up receive and keyboard handlers, plus any timers, and then sit in fish_main() for the rest of the program. packet reception, keyboard input and timer expiry are called from within fish_main() and return control to fish_main(). */ extern void fish_main(void); /* scheduleevent sets up a timer function to be called at some time in the future. you write the timer function, and supply an argument value that it will be invoked with. scheduleevent returns a handle to the timer event, which can be used to cancel it before it expires */ typedef void (*event_handler_t)(void *); typedef int event; extern event /* returns a handle */ fish_scheduleevent(int msec_delay, /* how long in the future before calling the event_handler function, in milliseconds */ void (*event_handler)(void *), /* the timer function that you wrote and want called */ void *event_handler_argument); /* any one piece of data that you want passed to the timer function when it is called */ /* use the following function to cancel a timer before it expires. it takes the handle returned when the timer was set up in the first place */ extern void *fish_cancelevent(event event_handle); /* set and get the fishnet debugging levels using the defined constants above. the level can be changed during program operation */ extern void fish_setdebuglevel(const int level); extern int fish_getdebuglevel(void); /* you can also print debugging info with the following function. the level is a fishnet debugging level, and the format string works like printf. debug lines are timestamped too. */ extern void fish_debug(const int level, const char* format, ...); /* you can send the output to a file if you don't like to see your screen fill with debugging information. Example: fish_setdebugoutput( fopen( "debugoutput", "w" ) ); */ /* Be careful when running two programs that try to write to the same file. */ extern void fish_setdebugoutput(FILE *f); /* Assignment #3 specific structures */ struct route_advertisement { int destination_address; int metric; }; #define MAX_ADVERTISEMENTS ( PACKET_DATA_SIZE / \ sizeof(struct route_advertisement)) struct routing_packet { int src; /* same as previous header */ int dst; int ttl; int protocol; /* data contents are not characters, they are route advertisements: */ struct route_advertisement adv[ MAX_ADVERTISEMENTS ]; }; /* End Assignment #3 specific structures */ /* Assignment #4 specific structures */ /* Maximum value of the port number that can be used by the transport layer*/ #define MAX_PORT_NUMBER 10000 /* Maximum value of the sequence number that can be used */ #define MAX_SEQ_NO 100000 /* Time (in seconds) after which a packet should be retransmitted if no acknowledgement has been recieved */ #define RETRANSMIT_TIMEOUT 1 /* The maximum number of retransmissions attempted by a sender. The connection is aborted by the sender after that */ #define MAX_RETRANSMIT 3 /* Time (in seconds) after which a connection is deleted by the recieve side, if no packet activity is seen during that time */ #define IDLE_TIMEOUT 10 #define TRANSPORT_HEADER_SIZE (sizeof(int)*5) #define TRANSPORT_DATA_SIZE (PACKET_DATA_SIZE - TRANSPORT_HEADER_SIZE) struct transport_packet { int src; /* same as previous header */ int dst; int ttl; int protocol; /* end packet header */ /* begin transport header */ int src_port; /* Source Port */ int dst_port; /* Destination Port */ int seq_no; /* Sequence Number For Data Packet (>0), ack_no is 0 if its a data packet*/ int ack_no; /* Acknowledgement (>0), seq_no is 0 if its an ack packet */ unsigned int syn:1; /* SYN flag */ unsigned int fin:1; /* FIN flag */ char data[TRANSPORT_DATA_SIZE]; /* the rest of the packet */ }; /* End Assignment #4 specific structures */ #endif /* __FISH_H__ */