Files
ios2024/code/network/post.h

152 lines
5.5 KiB
C++

// post.h
// Data structures for providing the abstraction of unreliable,
// ordered, fixed-size message delivery to mailboxes on other
// (directly connected) machines. Messages can be dropped by
// the network, but they are never corrupted.
//
// The US Post Office (and Canada Post! -KMS)
// delivers mail to the addressed mailbox.
// By analogy, our post office delivers packets to a specific buffer
// (MailBox), based on the mailbox number stored in the packet header.
// Mail waits in the box until a thread asks for it; if the mailbox
// is empty, threads can wait for mail to arrive in it.
//
// Thus, the service our post office provides is to de-multiplex
// incoming packets, delivering them to the appropriate thread.
//
// With each message, you get a return address, which consists of a "from
// address", which is the id of the machine that sent the message, and
// a "from box", which is the number of a mailbox on the sending machine
// to which you can send an acknowledgement, if your protocol requires
// this.
//
// Copyright (c) 1992-1996 The Regents of the University of California.
// All rights reserved. See copyright.h for copyright notice and limitation
// of liability and disclaimer of warranty provisions.
#ifndef POST_H
#define POST_H
#include "copyright.h"
#include "utility.h"
#include "callback.h"
#include "network.h"
#include "synchlist.h"
#include "synch.h"
// Mailbox address -- uniquely identifies a mailbox on a given machine.
// A mailbox is just a place for temporary storage for messages.
typedef int MailBoxAddress;
// The following class defines part of the message header.
// This is prepended to the message by the PostOffice, before the message
// is sent to the Network.
class MailHeader {
public:
MailBoxAddress to; // Destination mail box
MailBoxAddress from; // Mail box to reply to
unsigned length; // Bytes of message data (excluding the
// mail header)
};
// Maximum "payload" -- real data -- that can included in a single message
// Excluding the MailHeader and the PacketHeader
#define MaxMailSize (MaxPacketSize - sizeof(MailHeader))
// The following class defines the format of an incoming/outgoing
// "Mail" message. The message format is layered:
// network header (PacketHeader)
// post office header (MailHeader)
// data
class Mail {
public:
Mail(PacketHeader pktH, MailHeader mailH, char *msgData);
// Initialize a mail message by
// concatenating the headers to the data
PacketHeader pktHdr; // Header appended by Network
MailHeader mailHdr; // Header appended by PostOffice
char data[MaxMailSize]; // Payload -- message data
};
// The following class defines a single mailbox, or temporary storage
// for messages. Incoming messages are put by the PostOffice into the
// appropriate mailbox, and these messages can then be retrieved by
// threads on this machine.
class MailBox {
public:
MailBox(); // Allocate and initialize mail box
~MailBox(); // De-allocate mail box
void Put(PacketHeader pktHdr, MailHeader mailHdr, char *data);
// Atomically put a message into the mailbox
void Get(PacketHeader *pktHdr, MailHeader *mailHdr, char *data);
// Atomically get a message out of the
// mailbox (and wait if there is no message
// to get!)
private:
SynchList<Mail *> *messages; // A mailbox is just a list of arrived messages
};
// The following two classes defines a "Post Office", or a collection of
// mailboxes. The Post Office provides two main operations:
// Send -- send a message to a mailbox on a remote machine
// Receive -- wait until a message is in the mailbox, then remove and
// return it.
//
// Incoming messages are put by the PostOffice into the
// appropriate mailbox, waking up any threads waiting on Receive.
class PostOfficeInput : public CallBackObj {
public:
PostOfficeInput(int nBoxes); // Allocate and initialize Post Office
~PostOfficeInput(); // De-allocate Post Office data
void Receive(int box, PacketHeader *pktHdr,
MailHeader *mailHdr, char *data);
// Retrieve a message from "box". Wait if
// there is no message in the box.
static void PostalDelivery(void* data);
// Wait for incoming messages,
// and then put them in the correct mailbox
void CallBack(); // Called when incoming packet has arrived
// and can be pulled off of network
// (i.e., time to call PostalDelivery)
private:
NetworkInput *network; // Physical network connection
MailBox *boxes; // Table of mail boxes to hold incoming mail
int numBoxes; // Number of mail boxes
Semaphore *messageAvailable;// V'ed when message has arrived from network
};
class PostOfficeOutput : public CallBackObj {
public:
PostOfficeOutput(double reliability);
// Allocate and initialize output
// "reliability" is how many packets
// get dropped by the underlying network
~PostOfficeOutput(); // De-allocate Post Office data
void Send(PacketHeader pktHdr, MailHeader mailHdr, char *data);
// Send a message to a mailbox on a remote
// machine. The fromBox in the MailHeader is
// the return box for ack's.
void CallBack(); // Called when outgoing packet has been
// put on network; next packet can now be sent
private:
NetworkOutput *network; // Physical network connection
Semaphore *messageSent; // V'ed when next message can be sent to network
Lock *sendLock; // Only one outgoing message at a time
};
#endif