From ba066c34dde204aa192d03a23a81356374d93731 Mon Sep 17 00:00:00 2001 From: chatty Date: Wed, 7 Apr 1993 11:50:31 +0000 Subject: Initial revision --- comm/Datagram.cc | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 comm/Datagram.cc (limited to 'comm/Datagram.cc') diff --git a/comm/Datagram.cc b/comm/Datagram.cc new file mode 100644 index 0000000..b88deb5 --- /dev/null +++ b/comm/Datagram.cc @@ -0,0 +1,166 @@ +/* + * The Unix Channel + * + * by Michel Beaudouin-Lafon + * + * Copyright 1990-1993 + * Laboratoire de Recherche en Informatique (LRI) + * + * Datagrams + * + * $Id$ + * $CurLog$ + */ + +#include "Datagram.h" +#include "MsgBuffer.h" +#include +#include + +/*?class UchDatagram +A datagram socket can send to and receive from any other datagram socket, +unless it is connected. +Thus, establishing a datagram connection is simple. + +UchDatagram sockets are not reliable: messages can be lost, duplicated, or be received in a different order. +They keep the message boundaries: when \var{n} bytes are written, you will read at most \var{n} bytes; +but if you ask to read less than \var{n} bytes, then the end of the message will be lost. + +When a datagram socket is not connected, you must provide an address when you send a message; +when a message is read, the address of the sender can be retrieved (with function \fun{From}). +When a datagram socket is connected, messages can only be sent to and read from the +connected address. The \fun{Read} and \fun{Write} calls can be used in this case. + +Before any data can be sent or received, the socket must be set up with \fun{Setup}. +?*/ + +/*?nextdoc?*/ +UchDatagram :: UchDatagram () +: UchSocket (), + FAddr (0) +{ +} + +/*? +These constructors are similar to those of the class \typ{UchSocket}. +?*/ +UchDatagram :: UchDatagram (UchAddress* bound, UchAddress* connected) +: UchSocket (bound, connected), + FAddr (0) +{ +} + +/*?nodoc?*/ +UchDatagram :: UchDatagram (const UchDatagram& d) +: UchSocket (d), + FAddr (d.FAddr) +{ +} + +/*?nodoc?*/ +UchDatagram :: ~UchDatagram () +{ +} + +#ifdef DOC +/*? +Return the address of the sender of the last received message. +?*/ +UchAddress* +UchDatagram :: From () +{ } + +#endif /* DOC */ + +/*?nodoc?*/ +UchChannel* +UchDatagram :: Copy () const +{ + return new UchDatagram (*this); +} + +/*?nodoc?*/ +int +UchDatagram :: SockType () +{ + return SOCK_DGRAM; +} + +/*? +Send \var{len} bytes of \var{buf} on the datagram, to a destination address \var{to}. +Return the number of bytes actually transferred, or -1 if a system error occurred. +If the datagram is connected, you must use \fun{Write} instead. +?*/ +int +UchDatagram :: Send (byte* buf, int len, UchAddress& to) +{ + return sendto (FilDes (), (char*) buf, len, 0, to.GetSockAddr (), to.Length ()); +} + +/*? +Receive at most \var{len} bytes into \var{buf}. +Return the number of bytes actually transferred, or -1 if a system error occurred. +The address of the sender can be retrieved with \fun{From}. +If the socket is connected, you must use \fun{Read} instead. +?*/ +int +UchDatagram :: Receive (byte* buf, int len) +{ + GEN_ADDR addr; + int alen = sizeof (addr); + int ret; + + ret = recvfrom (FilDes (), (char*) buf, len, 0, &addr.sa, &alen); + if (ret < 0) + return ret; + + FAddr = UchAddress::Decode (&addr, alen); + return ret; +} + +/*? +This is equivalent to \fun{Send(buf, len, From ())}: +it sends \fun{len} bytes to the sender of the last received message. +If there is no such sender, it returns -1. +?*/ +int +UchDatagram :: Reply (byte* buf, int len) +{ + if (! FAddr) + return -1; + return sendto (FilDes (), (char*) buf, len, 0, FAddr->GetSockAddr (), FAddr->Length ()); +} + +/*?nextdoc?*/ +int +UchDatagram :: Send (UchMsgBuffer& buf, UchAddress& to, bool peek) +{ + int n = Send (buf.Buffer (), buf.BufLength (), to); + if (! peek) + buf.Flush (n); + return n; +} + +/*?nextdoc?*/ +int +UchDatagram :: Receive (UchMsgBuffer& buf) +{ + int n = Receive (buf.Free (), buf.FreeLength ()); + if (n > 0) + buf.More (n); + return n; +} + +/*? +The same functions but with a \typ{UchMsgBuffer} argument instead of a byte pointer and size. +As usual, if \var{peek} is TRUE the buffer is not flushed. +?*/ +int +UchDatagram :: Reply (UchMsgBuffer& buf, bool peek) +{ + int n = Reply (buf.Buffer (), buf.BufLength ()); + if (! peek) + buf.Flush (n); + return n; +} + -- cgit v1.1