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;
}
Example #3
0
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;
		}
	}
}