static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len) { size_t length; int offset; char *disk_ptr; int ret; DeclareThis(Buffer_t); if(!len) return 0; /*fprintf(stderr, "buf read %x %x %x\n", Stream, start, len);*/ switch(isInBuffer(This, start, &len)) { case OUTSIDE: case APPEND: /* always load until the end of the cylinder */ length = This->cylinderSize - (This->current + This->cur_size) % This->cylinderSize; maximize(length, This->size - This->cur_size); /* read it! */ ret=READS(This->Next, This->buf + This->cur_size, This->current + This->cur_size, length); if ( ret < 0 ) return ret; This->cur_size += ret; if (This->current+This->cur_size < start) { fprintf(stderr, "Short buffer fill\n"); exit(1); } break; case INSIDE: /* nothing to do */ break; case ERROR: return -1; } offset = OFFSET; disk_ptr = This->buf + offset; maximize(len, This->cur_size - offset); memcpy(buf, disk_ptr, len); return len; }
static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) { char *disk_ptr; DeclareThis(Buffer_t); int offset, ret; if(!len) return 0; This->ever_dirty = 1; #ifdef DEBUG fprintf(stderr, "buf write %x %02x %08x %08x -- %08x %08x -- %08x\n", Stream, (unsigned char) This->buf[0], start, len, This->current, This->cur_size, This->size); fprintf(stderr, "%d %d %d %x %x\n", start == This->current + This->cur_size, This->cur_size < This->size, len >= This->sectorSize, len, This->sectorSize); #endif switch(isInBuffer(This, start, &len)) { case OUTSIDE: #ifdef DEBUG fprintf(stderr, "outside\n"); #endif if(start % This->cylinderSize || len < This->sectorSize) { size_t readSize; readSize = This->cylinderSize - This->current % This->cylinderSize; ret=READS(This->Next, This->buf, This->current, readSize); /* read it! */ if ( ret < 0 ) return ret; This->cur_size = ret; /* for dosemu. Autoextend size */ if(!This->cur_size) { memset(This->buf,0,readSize); This->cur_size = readSize; } offset = OFFSET; break; } /* FALL THROUGH */ case APPEND: #ifdef DEBUG fprintf(stderr, "append\n"); #endif len = ROUND_DOWN(len, This->sectorSize); offset = OFFSET; maximize(len, This->size - offset); This->cur_size += len; if(This->Next->Class->pre_allocate) PRE_ALLOCATE(This->Next, This->current + This->cur_size); break; case INSIDE: /* nothing to do */ #ifdef DEBUG fprintf(stderr, "inside\n"); #endif offset = OFFSET; maximize(len, This->cur_size - offset); break; case ERROR: return -1; default: #ifdef DEBUG fprintf(stderr, "Should not happen\n"); #endif exit(1); } disk_ptr = This->buf + offset; /* extend if we write beyond end */ if(offset + len > This->cur_size) { len -= (offset + len) % This->sectorSize; This->cur_size = len + offset; } memcpy(disk_ptr, buf, len); if(!This->dirty || offset < This->dirty_pos) This->dirty_pos = ROUND_DOWN(offset, This->sectorSize); if(!This->dirty || offset + len > This->dirty_end) This->dirty_end = ROUND_UP(offset + len, This->sectorSize); if(This->dirty_end > This->cur_size) { fprintf(stderr, "Internal error, dirty end too big %x %x %x %d %x\n", This->dirty_end, (unsigned int) This->cur_size, (unsigned int) len, (int) offset, (int) This->sectorSize); fprintf(stderr, "offset + len + grain - 1 = %x\n", (int) (offset + len + This->sectorSize - 1)); fprintf(stderr, "ROUNDOWN(offset + len + grain - 1) = %x\n", (int)ROUND_DOWN(offset + len + This->sectorSize - 1, This->sectorSize)); fprintf(stderr, "This->dirty = %d\n", This->dirty); exit(1); } This->dirty = 1; return len; }
void main1(int argc, char** argv) { srand(time(0)); //init protocol_init(argc, argv); //arguments windowSize = 22; retimer = 3300;//retransmit timer acktimer = 600; bufferSize = windowSize / 2;//buffer size //init datalink layer senderLeft = 0;//left edge of sender senderRight = 0;//right edge of sender, which has data unfilled receiverLeft = 0;//left edge of receiver //receiverRight = bufferSize - 1;//right edge of receiver isPhysicalLayerReady = -1; lastAck = windowSize - 1; //init buffer sender = (buffer*)malloc(sizeof(buffer)* bufferSize); receiver = (buffer*)malloc(sizeof(buffer)* bufferSize); for (int i = 0; i < bufferSize; i++) { sender[i].frameArrived = false; receiver[i].frameArrived = false; sender[i].hasSent = false; receiver[i].hasSent = false; } //init interfcace enable_network_layer(); bool isNetworkEnabled = true; //init event args int eventArgs = -1; int eventKind = -1; //allocate temp space unsigned char temp[MAX_PACKET_SIZE + 11]; //main loop while (true) { static int frameLength; eventKind = wait_for_event(&eventArgs);//get event switch (eventKind) { case PHYSICAL_LAYER_READY: isPhysicalLayerReady = 1; break; case NETWORK_LAYER_READY: //if buffer nearly full if (((senderRight > senderLeft) && (senderRight - senderLeft == bufferSize - 1)) || (senderRight < senderLeft) && (windowSize - senderLeft + senderRight == bufferSize - 1)) { disable_network_layer(); isNetworkEnabled = false; } //store frame in buffer sender[senderRight % bufferSize].length = get_packet(sender[senderRight % bufferSize].data); //slide window senderRight = (senderRight + 1) % windowSize; break; case FRAME_RECEIVED: //init temperory variables frameLength = recv_frame(temp, MAX_PACKET_SIZE + 7); if (frameLength > MAX_PACKET_SIZE + 7) ;//frame is too large, discard it else { //check crc if (crc32(temp, frameLength) != 0) {//crc faild if (isInBuffer(senderLeft, senderRight, temp[0] == FRAME_DATA ? temp[2] : temp[1], false)) { //send nak temp[0] = FRAME_NAK;//if the 2nd byte is error, it may sends false nak, but it doesn't matter mySendFrame(temp, 2); } } else { if (temp[0] == FRAME_ACK) {//if it's an ack frame if (isInBuffer(senderLeft, senderRight, temp[1], false)) { if (isInBuffer(lastAck, senderRight, temp[1], false)) lastAck = temp[1]; //else do noting break; } } else if (temp[0] == FRAME_NAK) {//if it's a nak frame if (isInBuffer(senderLeft, senderRight, temp[1], false)) { //retranmit temp[0] = 1; memcpy(temp + 3, sender[temp[1] % bufferSize].data, sender[temp[1] % bufferSize].length * sizeof(unsigned char)); mySendFrame(temp, sender[temp[1] % bufferSize].length + 3); break; } } else if (temp[0] == FRAME_DATA) {//if it's a data frame if (isInBuffer(lastAck, senderRight, temp[2], false)) lastAck = temp[2]; if (isInBuffer(receiverLeft, (receiverLeft + bufferSize) % windowSize, temp[1], true)){ if (!receiver[temp[1] % bufferSize].frameArrived) { receiver[temp[1] % bufferSize].frameArrived = true; receiver[temp[1] % bufferSize].length = frameLength - 7; for (int i = 0; i < frameLength - 7; i++) { receiver[temp[1] % bufferSize].data[i] = temp[3 + i]; } } } } } } break; case DATA_TIMEOUT: //just retransmit the frame if (isInBuffer(lastAck, senderRight, eventArgs, false) && isInBuffer(senderLeft, senderRight, eventArgs, false)) { if (sender[eventArgs % bufferSize].hasSent) {//if it has been sent if (eventArgs == senderLeft || rand() % 10 > 10) { //build the frame temp[0] = FRAME_DATA; temp[1] = eventArgs; memcpy((void*)(temp + 3), sender[eventArgs % bufferSize].data, sender[eventArgs % bufferSize].length * sizeof(unsigned char)); //transmit mySendFrame(temp, sender[eventArgs % bufferSize].length + 3); } else start_timer(eventArgs, retimer * (rand() % 10 / 10.0 + 1)); } } break; case ACK_TIMEOUT: //just send an ack temp[0] = FRAME_ACK; mySendFrame(temp, 2); break; } //sliding the sender window //send { int i = senderLeft; while (isInBuffer(senderLeft, senderRight, i, false)) { if (sender[i % bufferSize].hasSent == false){ if (isPhysicalLayerReady == 1 || isPhysicalLayerReady == -1 || phl_sq_len() < 1000) { //build the frame temp[0] = FRAME_DATA; temp[1] = i % windowSize; memcpy((void*)(temp + 3), sender[i % bufferSize].data, sender[i % bufferSize].length * sizeof(unsigned char)); //transmit mySendFrame(temp, sender[i % bufferSize].length + 3); sender[i % bufferSize].hasSent = true; isPhysicalLayerReady = 0; } break; } i = (i + 1) % windowSize; } } //slide while (isInBuffer(senderLeft, senderRight, lastAck, false)) {//·â×°º¯Êý sender[senderLeft % bufferSize].hasSent = false; stop_timer(senderLeft); senderLeft = (senderLeft + 1) % windowSize; } //enable network layer if (!(((senderRight > senderLeft) && (senderRight - senderLeft == bufferSize)) || (senderRight < senderLeft) && (windowSize - senderLeft + senderRight == bufferSize)) && !isNetworkEnabled) { enable_network_layer(); isNetworkEnabled = true; } //sliding the receiver window { int i = 0; for (i = 0; i < bufferSize; i++) { if (receiver[(receiverLeft + i) % bufferSize].frameArrived) { put_packet(receiver[(receiverLeft + i) % bufferSize].data, receiver[(receiverLeft + i) % bufferSize].length); receiver[(receiverLeft + i) % bufferSize].frameArrived = false; } else break; } receiverLeft = (receiverLeft + i) % windowSize; } } }