blob: f24b49571fdffe85e58c955bf2458b5882c6c4d6 [file] [log] [blame]
dburgess82c46ff2011-10-07 02:40:51 +00001/*
2* Copyright 2008, 2010 Free Software Foundation, Inc.
3*
4*
5* This software is distributed under the terms of the GNU Affero Public License.
6* See the COPYING file in the main directory for details.
7*
8* This use of this software may be subject to additional restrictions.
9* See the LEGAL file in the main directory for details.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU Affero General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Affero General Public License for more details.
20
21 You should have received a copy of the GNU Affero General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24*/
25
26
27
28#include <unistd.h>
29#include <fcntl.h>
30#include <cstdio>
31#include <sys/select.h>
32
33#include "Threads.h"
34#include "Sockets.h"
35#include <stdio.h>
36#include <unistd.h>
37#include <fcntl.h>
38
39#include <string.h>
40#include <stdlib.h>
41
42
43
44
45
46
47bool resolveAddress(struct sockaddr_in *address, const char *hostAndPort)
48{
49 assert(address);
50 assert(hostAndPort);
51 char *copy = strdup(hostAndPort);
52 char *colon = strchr(copy,':');
53 if (!colon) return false;
54 *colon = '\0';
55 char *host = copy;
56 unsigned port = strtol(colon+1,NULL,10);
57 bool retVal = resolveAddress(address,host,port);
58 free(copy);
59 return retVal;
60}
61
62bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned short port)
63{
64 assert(address);
65 assert(host);
66 // FIXME -- Need to ignore leading/trailing spaces in hostname.
67 struct hostent *hp = gethostbyname(host);
68 if (hp==NULL) {
69 CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno));
70 return false;
71 }
72 address->sin_family = AF_INET;
73 bcopy(hp->h_addr, &(address->sin_addr), hp->h_length);
74 address->sin_port = htons(port);
75 return true;
76}
77
78
79
80DatagramSocket::DatagramSocket()
81{
82 bzero(mDestination,sizeof(mDestination));
83}
84
85
86
87
88
89void DatagramSocket::nonblocking()
90{
91 fcntl(mSocketFD,F_SETFL,O_NONBLOCK);
92}
93
94void DatagramSocket::blocking()
95{
96 fcntl(mSocketFD,F_SETFL,0);
97}
98
99void DatagramSocket::close()
100{
101 ::close(mSocketFD);
102}
103
104
105DatagramSocket::~DatagramSocket()
106{
107 close();
108}
109
110
111
112
113
114int DatagramSocket::write( const char * message, size_t length )
115{
116 assert(length<=MAX_UDP_LENGTH);
117 int retVal = sendto(mSocketFD, message, length, 0,
118 (struct sockaddr *)mDestination, addressSize());
119 if (retVal == -1 ) perror("DatagramSocket::write() failed");
120 return retVal;
121}
122
123int DatagramSocket::writeBack( const char * message, size_t length )
124{
125 assert(length<=MAX_UDP_LENGTH);
126 int retVal = sendto(mSocketFD, message, length, 0,
127 (struct sockaddr *)mSource, addressSize());
128 if (retVal == -1 ) perror("DatagramSocket::write() failed");
129 return retVal;
130}
131
132
133
134int DatagramSocket::write( const char * message)
135{
136 size_t length=strlen(message)+1;
137 return write(message,length);
138}
139
140int DatagramSocket::writeBack( const char * message)
141{
142 size_t length=strlen(message)+1;
143 return writeBack(message,length);
144}
145
146
147
148int DatagramSocket::send(const struct sockaddr* dest, const char * message, size_t length )
149{
150 assert(length<=MAX_UDP_LENGTH);
151 int retVal = sendto(mSocketFD, message, length, 0, dest, addressSize());
152 if (retVal == -1 ) perror("DatagramSocket::send() failed");
153 return retVal;
154}
155
156int DatagramSocket::send(const struct sockaddr* dest, const char * message)
157{
158 size_t length=strlen(message)+1;
159 return send(dest,message,length);
160}
161
162
163
164
165
166int DatagramSocket::read(char* buffer)
167{
168 socklen_t temp_len = sizeof(mSource);
169 int length = recvfrom(mSocketFD, (void*)buffer, MAX_UDP_LENGTH, 0,
170 (struct sockaddr*)&mSource,&temp_len);
171 if ((length==-1) && (errno!=EAGAIN)) {
172 perror("DatagramSocket::read() failed");
173 throw SocketError();
174 }
175 return length;
176}
177
178
179int DatagramSocket::read(char* buffer, unsigned timeout)
180{
181 fd_set fds;
182 FD_SET(mSocketFD,&fds);
183 struct timeval tv;
184 tv.tv_sec = timeout/1000;
185 tv.tv_usec = (timeout%1000)*1000;
186 int sel = select(mSocketFD+1,&fds,NULL,NULL,&tv);
187 if (sel<0) {
188 perror("DatagramSocket::read() select() failed");
189 throw SocketError();
190 }
191 if (sel==0) return -1;
192 return read(buffer);
193}
194
195
196
197
198
199
200UDPSocket::UDPSocket(unsigned short wSrcPort)
201 :DatagramSocket()
202{
203 open(wSrcPort);
204}
205
206
207UDPSocket::UDPSocket(unsigned short wSrcPort,
208 const char * wDestIP, unsigned short wDestPort )
209 :DatagramSocket()
210{
211 open(wSrcPort);
212 destination(wDestPort, wDestIP);
213}
214
215
216
217void UDPSocket::destination( unsigned short wDestPort, const char * wDestIP )
218{
219 resolveAddress((sockaddr_in*)mDestination, wDestIP, wDestPort );
220}
221
222
223void UDPSocket::open(unsigned short localPort)
224{
225 // create
226 mSocketFD = socket(AF_INET,SOCK_DGRAM,0);
227 if (mSocketFD<0) {
228 perror("socket() failed");
229 throw SocketError();
230 }
231
232 // bind
233 struct sockaddr_in address;
234 size_t length = sizeof(address);
235 bzero(&address,length);
236 address.sin_family = AF_INET;
237 address.sin_addr.s_addr = INADDR_ANY;
238 address.sin_port = htons(localPort);
239 if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
240 perror("bind() failed");
241 throw SocketError();
242 }
243}
244
245
246
247unsigned short UDPSocket::port() const
248{
249 struct sockaddr_in name;
250 socklen_t nameSize = sizeof(name);
251 int retVal = getsockname(mSocketFD, (struct sockaddr*)&name, &nameSize);
252 if (retVal==-1) throw SocketError();
253 return ntohs(name.sin_port);
254}
255
256
257
258
259
260UDDSocket::UDDSocket(const char* localPath, const char* remotePath)
261 :DatagramSocket()
262{
263 if (localPath!=NULL) open(localPath);
264 if (remotePath!=NULL) destination(remotePath);
265}
266
267
268
269void UDDSocket::open(const char* localPath)
270{
271 // create
272 mSocketFD = socket(AF_UNIX,SOCK_DGRAM,0);
273 if (mSocketFD<0) {
274 perror("socket() failed");
275 throw SocketError();
276 }
277
278 // bind
279 struct sockaddr_un address;
280 size_t length = sizeof(address);
281 bzero(&address,length);
282 address.sun_family = AF_UNIX;
283 strcpy(address.sun_path,localPath);
284 unlink(localPath);
285 if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
286 perror("bind() failed");
287 throw SocketError();
288 }
289}
290
291
292
293void UDDSocket::destination(const char* remotePath)
294{
295 struct sockaddr_un* unAddr = (struct sockaddr_un*)mDestination;
296 strcpy(unAddr->sun_path,remotePath);
297}
298
299
300
301
302// vim:ts=4:sw=4