1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
/* BLURB lgpl
Coda File System
Release 6
Copyright (c) 2006 Carnegie Mellon University
Additional copyrights listed below
This code is distributed "AS IS" without warranty of any kind under
the terms of the GNU Library General Public Licence Version 2, as
shown in the file LICENSE. The technical and financial contributors to
Coda are listed in the file CREDITS.
Additional copyrights
#*/
#include <stdlib.h>
#include "rpc2.private.h"
/* I don't think we should expect to wake up within a millisecond --JH */
#define RPC2_MINDELAY 1000
struct DelayEntry {
int sock;
struct RPC2_addrinfo *addr;
size_t len;
struct security_association *sa;
};
int rpc2_DelayedSend(int s, struct RPC2_addrinfo *addr, RPC2_PacketBuffer *pb,
struct timeval *tv)
{
struct SL_Entry *sl;
struct DelayEntry *de;
/* If delay is too short, just send it */
if (tv->tv_sec == 0 && tv->tv_usec < RPC2_MINDELAY) return 0;
sl = rpc2_AllocSle(DELAYED_SEND, NULL);
if (!sl) return 0; /* allocation failed, just send the packet now */
de = malloc(sizeof(struct DelayEntry) + pb->Prefix.LengthOfPacket);
if (!de) { rpc2_FreeSle(&sl); return 0; }
de->sock = s;
de->len = pb->Prefix.LengthOfPacket;
de->addr = RPC2_copyaddrinfo(addr);
/* hopefully the connection entry (and security association) are not
* destroyed during the delay period */
de->sa = pb->Prefix.sa;
memcpy(&de[1], &pb->Header, de->len);
/* enqueue */
sl->data = de;
say(9,RPC2_DebugLevel,"Delaying packet transmission for %p by %ld.%06lus\n",
de, tv->tv_sec, tv->tv_usec);
rpc2_ActivateSle(sl, tv);
return 1;
}
void rpc2_SendDelayedPacket(struct SL_Entry *sl)
{
struct DelayEntry *de = (struct DelayEntry *)sl->data;
say(9, RPC2_DebugLevel, "Sending delayed packet %p\n", de);
(void)secure_sendto(de->sock, &de[1], de->len, 0,
de->addr->ai_addr, de->addr->ai_addrlen, de->sa);
RPC2_freeaddrinfo(de->addr);
free(de);
rpc2_FreeSle(&sl);
}
int rpc2_DelayedRecv(RPC2_PacketBuffer *pb, struct timeval *tv)
{
struct SL_Entry *sl;
/* update the time we supposedly 'received' this packet */
pb->Prefix.RecvStamp.tv_usec += tv->tv_usec;
while (pb->Prefix.RecvStamp.tv_usec >= 1000000) {
pb->Prefix.RecvStamp.tv_usec -= 1000000;
pb->Prefix.RecvStamp.tv_sec++;
}
pb->Prefix.RecvStamp.tv_sec += tv->tv_sec;
/* If delay is too short, just accept it */
if (tv->tv_sec == 0 && tv->tv_usec < RPC2_MINDELAY) return 0;
sl = rpc2_AllocSle(DELAYED_RECV, NULL);
if (!sl) return 0; /* allocation failed, accept the packet now */
sl->data = pb;
say(9, RPC2_DebugLevel, "Delaying packet reception for %p by %ld.%06lus\n",
pb, tv->tv_sec, tv->tv_usec);
rpc2_ActivateSle(sl, tv);
return 1;
}
RPC2_PacketBuffer *rpc2_RecvDelayedPacket(struct SL_Entry *sl)
{
RPC2_PacketBuffer *pb = (RPC2_PacketBuffer *)sl->data;
say(9, RPC2_DebugLevel, "Receiving delayed packet %p\n", pb);
rpc2_FreeSle(&sl);
return pb;
}
|