Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include "protocol.h"
- #include "datalink.h"
- #define max(x, y) ((x) > (y) ? (x) : (y))
- #define min(x, y) ((x) < (y) ? (x) : (y))
- /* selective */
- #define DATA_TIMER 2500
- #define ACK_TIMER 1000
- #define SEQ_SIZE 44 // 序号空间大小
- #define MAX_SEND_WINDOW_SIZE (SEQ_SIZE / 2)
- #define MAX_RECV_WINDOW_SIZE (SEQ_SIZE / 2)
- #define CRC_CODE_LEN 4
- /* 宏函数,返回发送窗口的大小 */
- #define send_window_size() \
- (send_buffer_l <= send_buffer_r \
- ? send_buffer_r - send_buffer_l : send_buffer_r + SEQ_SIZE - send_buffer_l)
- /* 宏函数,返回x+1对序号空间大小取模的结果 */
- #define xadd1(x) ((x + 1) % SEQ_SIZE)
- /* 宏函数,返回x-1对序号空间大小取模的结果 */
- #define xsub1(x) ((x - 1 + SEQ_SIZE) % SEQ_SIZE)
- /* 帧的头部的大小,也就是data字段在FRAME结构体中的偏移量 */
- #define FRAME_HEAD_SIZE ((unsigned long)&(((struct FRAME*)NULL)->data))
- struct FRAME {
- unsigned char kind; /* 帧的类型 */
- unsigned char ack; /* 数据帧中捎带的ACK字段、ACK帧中的ACK字段、NAK帧中的NAK字段 */
- unsigned char seq; /* 帧的序号字段 */
- unsigned char data[PKT_LEN]; /* 帧的数据字段 */
- unsigned int padding; /* 四字节填充,给CRC校验留位置 */
- };
- /* 发送缓冲,发送窗口左边界,发送窗口右边界(左开右闭) */
- static unsigned char send_buff[SEQ_SIZE][PKT_LEN], send_buffer_l = 0, send_buffer_r = 0;
- /* 发送缓冲中数据帧中数据的长度 */
- static unsigned int send_data_len[SEQ_SIZE];
- /* 接收缓冲,接收窗口左边界,接收窗口右边界(左开右闭) */
- static unsigned char recv_buff[SEQ_SIZE][PKT_LEN], recv_buffer_l = 0, recv_buffer_r = MAX_RECV_WINDOW_SIZE;
- /* 接收缓冲中数据帧中数据的长度 */
- static unsigned int recv_data_len[SEQ_SIZE];
- /* 将接收缓冲中数据的长度当成bool值来标识接收窗口中的某一帧是否已经收到 */
- #define received recv_data_len
- /* 上一次发送的NAK编号 */
- static unsigned char last_nak = SEQ_SIZE - 1;
- /* 物理层是否准备好 */
- static int phl_ready = 0;
- /*
- * 判断序号k是否在窗口左边界l和右边界r之间
- * l: 窗口左边界
- * r: 窗口右边界
- * k: 要被判断的序号
- */
- static int between(unsigned char l, unsigned char r, int k) {
- return (l <= k && k < r) || (l > r && l <= k) || (l > r && k < r);
- }
- /*
- * 在帧末尾添上crc32校验位,然后发送一帧到物理层
- * frame: 指向要发送的整个帧的指针
- * len: 要发送的该帧的长度(包括帧头部一直到数据的结尾,不包括crc校验位)
- */
- static void put_frame(unsigned char *frame, unsigned int len) {
- *(unsigned int *)(frame + len) = crc32(frame, len);
- send_frame(frame, len + 4);
- phl_ready = 0;
- }
- /*
- * 从发送缓冲中读取序号为seq的数据帧发送
- * seq: 将要发送的数据帧号
- */
- static void send_data_frame(unsigned char seq) {
- struct FRAME s;
- s.kind = FRAME_DATA;
- s.seq = seq;
- s.ack = xsub1(recv_buffer_l);
- memcpy(s.data, send_buff[seq], send_data_len[seq]);
- dbg_frame("Send DATA %d %d, ID %d\n", s.seq, s.ack, *(short *)s.data);
- put_frame((unsigned char *)&s, FRAME_HEAD_SIZE + send_data_len[seq]);
- stop_ack_timer();
- start_timer(seq, DATA_TIMER);
- }
- /*
- * 发送一个ack帧作为对序号为ack的数据帧的回应
- * ack: 要回复的数据帧的序号
- */
- static void send_ack_frame(unsigned char ack) {
- struct FRAME s;
- s.kind = FRAME_ACK;
- s.ack = ack;
- dbg_frame("Send ACK %d\n", s.ack);
- put_frame((unsigned char *)&s, 2);
- }
- /*
- * 发送一个nak帧给发送方
- * nak: nak帧编号
- */
- static void send_nak_frame(unsigned char nak) {
- struct FRAME s;
- s.kind = FRAME_NAK;
- s.ack = nak;// nak
- dbg_frame("Send NAK %d\n", s.ack);
- put_frame((unsigned char *)&s, 2);
- last_nak = nak;
- }
- /*
- * 程序主函数
- * argc: 参数个数
- * argv: 参数字符串指针
- */
- int main(int argc, char **argv) {
- int event, arg;
- struct FRAME f;
- int len = 0;
- protocol_init(argc, argv);
- lprintf("Designed by imlk, build: " __DATE__" "__TIME__"\n");
- disable_network_layer();
- for (;;) {
- event = wait_for_event(&arg);
- switch (event) {
- case NETWORK_LAYER_READY:
- send_buffer_r = xadd1(send_buffer_r);
- unsigned int get_packet_len = get_packet(send_buff[xsub1(send_buffer_r)]);
- send_data_len[xsub1(send_buffer_r)] = get_packet_len;
- send_data_frame(xsub1(send_buffer_r));
- break;
- case PHYSICAL_LAYER_READY:
- phl_ready = 1;
- break;
- case FRAME_RECEIVED:
- len = recv_frame((unsigned char *)&f, sizeof f);
- if (len < 5 || crc32((unsigned char *)&f, len) != 0) {
- dbg_event("**** Receiver Error, Bad CRC Checksum\n");
- break;
- }
- if (f.kind == FRAME_NAK) {
- dbg_frame("Recv NAK %d\n", f.ack);
- send_data_frame(f.ack);
- // start_timer(f.ack, DATA_TIMER);
- break;
- }
- if (f.kind == FRAME_ACK)
- dbg_frame("Recv ACK %d\n", f.ack);
- if (f.kind == FRAME_DATA) {
- dbg_frame("Recv DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);
- len -= (FRAME_HEAD_SIZE + CRC_CODE_LEN);
- // 是想要的数据
- if (between(recv_buffer_l, recv_buffer_r, f.seq)) {
- // 是新包
- if (!received[f.seq]) {
- memcpy(recv_buff[f.seq], f.data, len);
- recv_data_len[f.seq] = len;
- }
- if (!received[recv_buffer_l]) {
- if (last_nak != recv_buffer_l) {
- send_nak_frame(recv_buffer_l);
- }
- }
- // 传送收到的包到网络层
- while (received[recv_buffer_l]) {
- put_packet(recv_buff[recv_buffer_l], recv_data_len[recv_buffer_l]);
- recv_buffer_l = xadd1(recv_buffer_l);
- received[recv_buffer_r] = 0;
- recv_buffer_r = xadd1(recv_buffer_r);
- }
- }
- start_ack_timer(ACK_TIMER);
- }
- if (between(send_buffer_l, send_buffer_r, f.ack)) { // 在发送区间内
- while (send_buffer_l != xadd1(f.ack)) {
- stop_timer(send_buffer_l);
- send_buffer_l = xadd1(send_buffer_l);
- }
- }
- break;
- case DATA_TIMEOUT:
- dbg_event("---- DATA_TIMEOUT\n");
- send_data_frame(send_buffer_l);
- break;
- case ACK_TIMEOUT:
- send_ack_frame(xsub1(recv_buffer_l));
- break;
- }
- dbg_event("---- PHYSICAL_SQ_LEN %d\n", phl_sq_len());
- if (send_window_size() < MAX_SEND_WINDOW_SIZE && phl_ready) {
- enable_network_layer();
- } else {
- disable_network_layer();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement