Main Page | Alphabetical List | Class List | File List | Class Members | File Members

network.cc

Go to the documentation of this file.
00001 // network.cc 00002 // Routines to simulate a network interface, using UNIX sockets 00003 // to deliver packets between multiple invocations of nachos. 00004 // 00005 // DO NOT CHANGE -- part of the machine emulation 00006 // 00007 // Copyright (c) 1992-1993 The Regents of the University of California. 00008 // All rights reserved. See copyright.h for copyright notice and limitation 00009 // of liability and disclaimer of warranty provisions. 00010 00011 #include "copyright.h" 00012 #include "system.h" 00013 #include <strings.h> 00014 00015 // Dummy functions because C++ can't call member functions indirectly 00016 static void NetworkReadPoll(int arg) 00017 { Network *net = (Network *)arg; net->CheckPktAvail(); } 00018 static void NetworkSendDone(int arg) 00019 { Network *net = (Network *)arg; net->SendDone(); } 00020 00021 // Initialize the network emulation 00022 // addr is used to generate the socket name 00023 // reliability says whether we drop packets to emulate unreliable links 00024 // readAvail, writeDone, callArg -- analogous to console 00025 Network::Network(NetworkAddress addr, double reliability, 00026 VoidFunctionPtr readAvail, VoidFunctionPtr writeDone, int callArg) 00027 { 00028 ident = addr; 00029 if (reliability < 0) chanceToWork = 0; 00030 else if (reliability > 1) chanceToWork = 1; 00031 else chanceToWork = reliability; 00032 00033 // set up the stuff to emulate asynchronous interrupts 00034 writeHandler = writeDone; 00035 readHandler = readAvail; 00036 handlerArg = callArg; 00037 sendBusy = FALSE; 00038 inHdr.length = 0; 00039 00040 sock = OpenSocket(); 00041 sprintf(sockName, "SOCKET_%d", (int)addr); 00042 AssignNameToSocket(sockName, sock); // Bind socket to a filename 00043 // in the current directory. 00044 00045 // start polling for incoming packets 00046 interrupt->Schedule(NetworkReadPoll, (int)this, NetworkTime, NetworkRecvInt); 00047 } 00048 00049 Network::~Network() 00050 { 00051 CloseSocket(sock); 00052 DeAssignNameToSocket(sockName); 00053 } 00054 00055 // if a packet is already buffered, we simply delay reading 00056 // the incoming packet. In real life, the incoming 00057 // packet might be dropped if we can't read it in time. 00058 void 00059 Network::CheckPktAvail() 00060 { 00061 // schedule the next time to poll for a packet 00062 interrupt->Schedule(NetworkReadPoll, (int)this, NetworkTime, NetworkRecvInt); 00063 00064 if (inHdr.length != 0) // do nothing if packet is already buffered 00065 return; 00066 if (!PollSocket(sock)) // do nothing if no packet to be read 00067 return; 00068 00069 // otherwise, read packet in 00070 char *buffer = new char[MaxWireSize]; 00071 ReadFromSocket(sock, buffer, MaxWireSize); 00072 00073 // divide packet into header and data 00074 inHdr = *(PacketHeader *)buffer; 00075 ASSERT((inHdr.to == ident) && (inHdr.length <= MaxPacketSize)); 00076 bcopy(buffer + sizeof(PacketHeader), inbox, inHdr.length); 00077 delete []buffer ; 00078 00079 DEBUG('n', "Network received packet from %d, length %d...\n", 00080 (int) inHdr.from, inHdr.length); 00081 stats->numPacketsRecvd++; 00082 00083 // tell post office that the packet has arrived 00084 (*readHandler)(handlerArg); 00085 } 00086 00087 // notify user that another packet can be sent 00088 void 00089 Network::SendDone() 00090 { 00091 sendBusy = FALSE; 00092 stats->numPacketsSent++; 00093 (*writeHandler)(handlerArg); 00094 } 00095 00096 // send a packet by concatenating hdr and data, and schedule 00097 // an interrupt to tell the user when the next packet can be sent 00098 // 00099 // Note we always pad out a packet to MaxWireSize before putting it into 00100 // the socket, because it's simpler at the receive end. 00101 void 00102 Network::Send(PacketHeader hdr, char* data) 00103 { 00104 char toName[32]; 00105 00106 sprintf(toName, "SOCKET_%d", (int)hdr.to); 00107 00108 ASSERT((sendBusy == FALSE) && (hdr.length > 0) 00109 && (hdr.length <= MaxPacketSize) && (hdr.from == ident)); 00110 DEBUG('n', "Sending to addr %d, %d bytes... ", hdr.to, hdr.length); 00111 00112 interrupt->Schedule(NetworkSendDone, (int)this, NetworkTime, NetworkSendInt); 00113 00114 if (Random() % 100 >= chanceToWork * 100) { // emulate a lost packet 00115 DEBUG('n', "oops, lost it!\n"); 00116 return; 00117 } 00118 00119 // concatenate hdr and data into a single buffer, and send it out 00120 char *buffer = new char[MaxWireSize]; 00121 *(PacketHeader *)buffer = hdr; 00122 bcopy(data, buffer + sizeof(PacketHeader), hdr.length); 00123 SendToSocket(sock, buffer, MaxWireSize, toName); 00124 delete []buffer; 00125 } 00126 00127 // read a packet, if one is buffered 00128 PacketHeader 00129 Network::Receive(char* data) 00130 { 00131 PacketHeader hdr = inHdr; 00132 00133 inHdr.length = 0; 00134 if (hdr.length != 0) 00135 bcopy(inbox, data, hdr.length); 00136 return hdr; 00137 }

Generated on Thu Sep 16 12:33:45 2004 for NachOS by doxygen 1.3.8