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

Generated on Mon Feb 10 09:54:46 2003 for nachos by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees