blob: cb952c0c6c3fa2c53e9016a6ed33472351c807b1 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#ifndef __PJPP_SOCK_HPP__
20#define __PJPP_SOCK_HPP__
21
22#include <pj/sock.h>
23#include <pj/string.h>
24
25class Pj_Event_Handler;
26
27//
28// Base class for address.
29//
30class Pj_Addr
31{
32};
33
34//
35// Internet address.
36//
37class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr
38{
39public:
40 //
41 // Get port number.
42 //
43 pj_uint16_t get_port_number() const
44 {
45 return pj_sockaddr_in_get_port(this);
46 }
47
48 //
49 // Set port number.
50 //
51 void set_port_number(pj_uint16_t port)
52 {
53 sin_family = PJ_AF_INET;
54 pj_sockaddr_in_set_port(this, port);
55 }
56
57 //
58 // Get IP address.
59 //
60 pj_uint32_t get_ip_address() const
61 {
62 return pj_sockaddr_in_get_addr(this).s_addr;
63 }
64
65 //
66 // Get address string.
67 //
68 const char *get_address() const
69 {
70 return pj_inet_ntoa(sin_addr);
71 }
72
73 //
74 // Set IP address.
75 //
76 void set_ip_address(pj_uint32_t addr)
77 {
78 sin_family = PJ_AF_INET;
79 pj_sockaddr_in_set_addr(this, addr);
80 }
81
82 //
83 // Set address.
84 //
85 pj_status_t set_address(const pj_str_t *addr)
86 {
87 return pj_sockaddr_in_set_str_addr(this, addr);
88 }
89
90 //
91 // Set address.
92 //
93 pj_status_t set_address(const char *addr)
94 {
95 pj_str_t s;
96 return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));
97 }
98
99 //
100 // Compare for equality.
101 //
102 bool operator==(const Pj_Inet_Addr &rhs) const
103 {
104 return sin_family == rhs.sin_family &&
105 sin_addr.s_addr == rhs.sin_addr.s_addr &&
106 sin_port == rhs.sin_port;
107 }
108
109private:
110 //
111 // Dummy length used in pj_ioqueue_recvfrom() etc
112 //
113 friend class Pj_Event_Handler;
114 friend class Pj_Socket;
115 friend class Pj_Sock_Stream;
116 friend class Pj_Sock_Dgram;
117
118 int addrlen_;
119};
120
121
122//
123// Socket base class.
124//
125// Note:
126// socket will not automatically be closed on destructor.
127//
128class Pj_Socket
129{
130public:
131 //
132 // Default constructor.
133 //
134 Pj_Socket()
135 : sock_(PJ_INVALID_SOCKET)
136 {
137 }
138
139 //
140 // Initialize from a socket handle.
141 //
142 explicit Pj_Socket(pj_sock_t sock)
143 : sock_(sock)
144 {
145 }
146
147 //
148 // Copy constructor.
149 //
150 Pj_Socket(const Pj_Socket &rhs)
151 : sock_(rhs.sock_)
152 {
153 }
154
155 //
156 // Destructor will not close the socket.
157 // You must call close() explicitly.
158 //
159 ~Pj_Socket()
160 {
161 }
162
163 //
164 // Set socket handle.
165 //
166 void set_handle(pj_sock_t sock)
167 {
168 sock_ = sock;
169 }
170
171 //
172 // Get socket handle.
173 //
174 pj_sock_t get_handle() const
175 {
176 return sock_;
177 }
178
179 //
180 // Get socket handle.
181 //
182 pj_sock_t& get_handle()
183 {
184 return sock_;
185 }
186
187 //
188 // See if the socket is valid.
189 //
190 bool is_valid() const
191 {
192 return sock_ != PJ_INVALID_SOCKET;
193 }
194
195 //
196 // Create the socket.
197 //
198 pj_status_t create(int af, int type, int proto)
199 {
200 return pj_sock_socket(af, type, proto, &sock_);
201 }
202
203 //
204 // Bind socket.
205 //
206 pj_status_t bind(const Pj_Inet_Addr &addr)
207 {
208 return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));
209 }
210
211 //
212 // Close socket.
213 //
214 pj_status_t close()
215 {
216 pj_sock_close(sock_);
217 }
218
219 //
220 // Get peer socket name.
221 //
222 pj_status_t getpeername(Pj_Inet_Addr *addr)
223 {
224 return pj_sock_getpeername(sock_, addr, &addr->addrlen_);
225 }
226
227 //
228 // getsockname
229 //
230 pj_status_t getsockname(Pj_Inet_Addr *addr)
231 {
232 return pj_sock_getsockname(sock_, addr, &addr->addrlen_);
233 }
234
235 //
236 // getsockopt.
237 //
Benny Prijonoac9d1422006-01-18 23:32:27 +0000238 pj_status_t getsockopt(pj_uint16_t level, pj_uint16_t optname,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000239 void *optval, int *optlen)
240 {
241 return pj_sock_getsockopt(sock_, level, optname, optval, optlen);
242 }
243
244 //
245 // setsockopt
246 //
Benny Prijonoac9d1422006-01-18 23:32:27 +0000247 pj_status_t setsockopt(pj_uint16_t level, pj_uint16_t optname,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000248 const void *optval, int optlen)
249 {
250 return pj_sock_setsockopt(sock_, level, optname, optval, optlen);
251 }
252
253 //
254 // receive data.
255 //
256 pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)
257 {
258 pj_ssize_t bytes = len;
259 if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)
260 return -1;
261 return bytes;
262 }
263
264 //
265 // send data.
266 //
267 pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)
268 {
269 pj_ssize_t bytes = len;
270 if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS)
271 return -1;
272 return bytes;
273 }
274
275 //
276 // connect.
277 //
278 pj_status_t connect(const Pj_Inet_Addr &addr)
279 {
280 return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr));
281 }
282
283 //
284 // assignment.
285 //
286 Pj_Socket &operator=(const Pj_Socket &rhs)
287 {
288 sock_ = rhs.sock_;
289 return *this;
290 }
291
292protected:
293 friend class Pj_Event_Handler;
294 pj_sock_t sock_;
295};
296
297
298#if PJ_HAS_TCP
299//
300// Stream socket.
301//
302class Pj_Sock_Stream : public Pj_Socket
303{
304public:
305 //
306 // Default constructor.
307 //
308 Pj_Sock_Stream()
309 {
310 }
311
312 //
313 // Initialize from a socket handle.
314 //
315 explicit Pj_Sock_Stream(pj_sock_t sock)
316 : Pj_Socket(sock)
317 {
318 }
319
320 //
321 // Copy constructor.
322 //
323 Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs)
324 {
325 }
326
327 //
328 // Assignment.
329 //
330 Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs)
331 {
332 sock_ = rhs.sock_;
333 return *this;
334 }
335
336 //
337 // listen()
338 //
339 pj_status_t listen(int backlog = 5)
340 {
341 return pj_sock_listen(sock_, backlog);
342 }
343
344 //
345 // blocking accept()
346 //
347 Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL)
348 {
349 pj_sock_t newsock;
350 int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL;
351 pj_status_t status;
352
353 status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen);
354 if (status != PJ_SUCCESS)
355 return Pj_Sock_Stream(-1);
356
357 return Pj_Sock_Stream(newsock);
358 }
359
360 //
361 // shutdown()
362 //
363 pj_status_t shutdown(int how = PJ_SHUT_RDWR)
364 {
365 return pj_sock_shutdown(sock_, how);
366 }
367
368};
369#endif
370
371//
372// Datagram socket.
373//
374class Pj_Sock_Dgram : public Pj_Socket
375{
376public:
377 //
378 // Default constructor.
379 //
380 Pj_Sock_Dgram()
381 {
382 }
383
384 //
385 // Initialize from a socket handle.
386 //
387 explicit Pj_Sock_Dgram(pj_sock_t sock)
388 : Pj_Socket(sock)
389 {
390 }
391
392 //
393 // Copy constructor.
394 //
395 Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs)
396 : Pj_Socket(rhs)
397 {
398 }
399
400 //
401 // Assignment.
402 //
403 Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs)
404 {
405 Pj_Socket::operator =(rhs);
406 return *this;
407 }
408
409 //
410 // recvfrom()
411 //
412 pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0,
413 Pj_Inet_Addr *fromaddr = NULL)
414 {
415 pj_ssize_t bytes = len;
416 int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL;
417 if (pj_sock_recvfrom( sock_, buf, &bytes, flag,
418 fromaddr, addrlen) != PJ_SUCCESS)
419 {
420 return -1;
421 }
422 return bytes;
423 }
424
425 //
426 // sendto()
427 //
428 pj_ssize_t sendto( const void *buf, pj_size_t len, int flag,
429 const Pj_Inet_Addr &addr)
430 {
431 pj_ssize_t bytes = len;
432 if (pj_sock_sendto( sock_, buf, &bytes, flag,
433 &addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS)
434 {
435 return -1;
436 }
437 return bytes;
438 }
439};
440
441
442#endif /* __PJPP_SOCK_HPP__ */
443