File: libudpcla.c

package info (click to toggle)
ion 3.2.1%2Bdfsg-1.1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 23,768 kB
  • ctags: 11,049
  • sloc: ansic: 141,798; sh: 22,848; makefile: 7,818; python: 1,638; sql: 311; perl: 197; awk: 178; xml: 50; java: 19
file content (169 lines) | stat: -rw-r--r-- 3,430 bytes parent folder | download | duplicates (2)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
	libudpcla.c:	common functions for BP UDP-based
			convergence-layer daemons.

	Author: Ted Piotrowski, APL 
		Scott Burleigh, JPL

	Copyright (c) 2006, California Institute of Technology.
	ALL RIGHTS RESERVED.  U.S. Government Sponsorship
	acknowledged.
	
									*/
#include "udpcla.h"

/*	*	*	Sender functions	*	*	*	*/

static int	openUdpSocket(int *sock)
{
	*sock = -1;

	*sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (*sock < 0)
	{
		putSysErrmsg("CLO can't open UDP socket", NULL);
		return -1;
	}

	return 0;
}

int	sendBytesByUDP(int *bundleSocket, char *from, int length,
		struct sockaddr* socketName)
{
	int	bytesWritten;

	CHKERR(socketName && bundleSocket && from);
	while (1)	/*	Continue until not interrupted.		*/
	{
		bytesWritten = isendto(*bundleSocket, from, length, 0,
			socketName, sizeof(struct sockaddr));
		if (bytesWritten < 0)
		{
			switch (errno)
			{
			case EINTR:	/*	Interrupted; retry.	*/
				continue;

			case EPIPE:	/*	Lost connection.	*/
			case EBADF:
			case ETIMEDOUT:
			case ECONNRESET:
				closesocket(*bundleSocket);
				*bundleSocket = -1;
			}

			putSysErrmsg("CLO write() error on socket", NULL);
		}

		return bytesWritten;
	}
}

int	sendBundleByUDP(struct sockaddr *socketName, int *bundleSocket,
		unsigned int bundleLength, Object bundleZco,
		unsigned char *buffer)
{
	Sdr		sdr;
	ZcoReader	reader;
	int		bytesToSend;
	int		bytesSent;

	CHKERR(socketName && bundleSocket && buffer);
	if (bundleLength > UDPCLA_BUFSZ)
	{
		putErrmsg("Bundle is too big for UDP CLA.", itoa(bundleLength));
		return -1;
	}

	/*	Connect to CLI as necessary.				*/

	if (*bundleSocket < 0)
	{
		if (openUdpSocket(bundleSocket) < 0)
		{
			/*	Treat I/O error as a transient anomaly,
			 *	note incomplete transmission.		*/

			return 0;
		}
	}

	/*	Send the bundle in a single UDP datagram.		*/

	sdr = getIonsdr();
	zco_start_transmitting(bundleZco, &reader);
	zco_track_file_offset(&reader);
	CHKERR(sdr_begin_xn(sdr));
	bytesToSend = zco_transmit(sdr, &reader, UDPCLA_BUFSZ, (char *) buffer);
	if (sdr_end_xn(sdr) < 0 || bytesToSend < 0)
	{
		putErrmsg("Can't issue from ZCO.", NULL);
		return -1;
	}

	bytesSent = sendBytesByUDP(bundleSocket, (char *) buffer, bytesToSend,
			socketName);
	if (bytesSent < 0)
	{
		if (bpHandleXmitFailure(bundleZco))
		{
			putErrmsg("Can't handle xmit failure.", NULL);
			return -1;
		}

		if (*bundleSocket == -1)
		{
			/*	Just lost connection; treat as a
			 *	transient anomaly, note the incomplete
			 *	transmission.				*/

			writeMemo("[i] Lost UDP connection to CLI; restart CLO \
when connectivity is restored.");
			bytesSent = 0;
		}
		else
		{
			/*	Big problem; shut down.			*/

			putErrmsg("Failed to send by UDP.", NULL);
			return -1;
		}
	}

	CHKERR(sdr_begin_xn(sdr));
	zco_destroy(sdr, bundleZco);
	if (sdr_end_xn(sdr) < 0)
	{
		putErrmsg("Can't destroy bundle ZCO.", NULL);
		return -1;
	}

	return bytesSent;
}

/*	*	*	Receiver functions	*	*	*	*/

int	receiveBytesByUDP(int bundleSocket, struct sockaddr_in *fromAddr,
		char *into, int length)
{
	int		bytesRead;
	socklen_t	fromSize;

	CHKERR(fromAddr && length);
	fromSize = sizeof(struct sockaddr_in);
	bytesRead = irecvfrom(bundleSocket, into, length, 0,
			(struct sockaddr *) fromAddr, &fromSize);
	if (bytesRead < 0)
	{
		if (errno == EBADF)	/*	Shutdown.		*/
		{
			return 0;
		}

		putSysErrmsg("CLI read() error on socket", NULL);
		return -1;
	}

	return bytesRead;
}