]> git.tdb.fi Git - libs/net.git/blob - source/net/clientsocket.cpp
Add a dynamic receiver class for more flexible packet handling
[libs/net.git] / source / net / clientsocket.cpp
1 #include "platform_api.h"
2 #include "clientsocket.h"
3 #include <msp/core/systemerror.h>
4 #include "socket_private.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace Net {
10
11 ClientSocket::ClientSocket(Family af, int type, int proto):
12         Socket(af, type, proto)
13 { }
14
15 ClientSocket::ClientSocket(const Private &p, const SockAddr &paddr):
16         Socket(p),
17         connected(true),
18         peer_addr(paddr.copy())
19 { }
20
21 ClientSocket::~ClientSocket()
22 {
23         signal_flush_required.emit();
24 }
25
26 void ClientSocket::shutdown(IO::Mode m)
27 {
28         int how;
29         m = m&IO::M_RDWR;
30 #ifdef _WIN32
31         if(m==IO::M_READ)
32                 how = SD_RECEIVE;
33         else if(m==IO::M_WRITE)
34                 how = SD_SEND;
35         else if(m==IO::M_RDWR)
36                 how = SD_BOTH;
37 #else
38         if(m==IO::M_READ)
39                 how = SHUT_RD;
40         else if(m==IO::M_WRITE)
41                 how = SHUT_WR;
42         else if(m==IO::M_RDWR)
43                 how = SHUT_RDWR;
44 #endif
45         else
46                 return;
47
48         ::shutdown(priv->handle, how);
49         mode = mode&~m;
50 }
51
52 const SockAddr &ClientSocket::get_peer_address() const
53 {
54         if(!peer_addr)
55                 throw bad_socket_state("not connected");
56         return *peer_addr;
57 }
58
59 size_t ClientSocket::do_write(const char *buf, size_t size)
60 {
61         check_access(IO::M_WRITE);
62         if(!connected)
63                 throw bad_socket_state("not connected");
64
65         if(size==0)
66                 return 0;
67
68         return check_sys_error(::send(priv->handle, buf, size, 0), "send");
69 }
70
71 size_t ClientSocket::do_read(char *buf, size_t size)
72 {
73         check_access(IO::M_READ);
74         if(!connected)
75                 throw bad_socket_state("not connected");
76
77         // XXX This breaks level-triggered semantics on Windows
78         if(size==0)
79                 return 0;
80
81         make_signed<size_t>::type ret = ::recv(priv->handle, buf, size, 0);
82         if(ret==0)
83         {
84                 if(!eof_flag)
85                 {
86                         set_socket_events(S_NONE);
87                         set_eof();
88                 }
89                 return 0;
90         }
91
92         return check_sys_error(ret, "recv");
93 }
94
95 } // namespace Net
96 } // namespace Msp