/* * 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. Datagram 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}. ?*/ /*? 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 (Fd, (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; }