]> git.tdb.fi Git - libs/net.git/blob - source/net/clientsocket.cpp
d28d0e90b930487b4a573cb751356baf10575666
[libs/net.git] / source / net / clientsocket.cpp
1 #ifdef WIN32
2 #include <winsock2.h>
3 #else
4 #include <cerrno>
5 #include <sys/socket.h>
6 #endif
7 #include <msp/core/systemerror.h>
8 #include "clientsocket.h"
9 #include "socket_private.h"
10
11 namespace Msp {
12 namespace Net {
13
14 ClientSocket::ClientSocket(Family af, int type, int proto):
15         Socket(af, type, proto),
16         connecting(false),
17         connected(false),
18         peer_addr(0)
19 { }
20
21 ClientSocket::ClientSocket(const Private &p, const SockAddr &paddr):
22         Socket(p),
23         connecting(false),
24         connected(true),
25         peer_addr(paddr.copy())
26 { }
27
28 ClientSocket::~ClientSocket()
29 {
30         signal_flush_required.emit();
31
32         delete peer_addr;
33 }
34
35 void ClientSocket::shutdown(IO::Mode m)
36 {
37         int how;
38         m = m&IO::M_RDWR;
39 #ifdef WIN32
40         if(m==IO::M_READ)
41                 how = SD_RECEIVE;
42         else if(m==IO::M_WRITE)
43                 how = SD_SEND;
44         else if(m==IO::M_RDWR)
45                 how = SD_BOTH;
46 #else
47         if(m==IO::M_READ)
48                 how = SHUT_RD;
49         else if(m==IO::M_WRITE)
50                 how = SHUT_WR;
51         else if(m==IO::M_RDWR)
52                 how = SHUT_RDWR;
53 #endif
54         else
55                 return;
56
57         ::shutdown(priv->handle, how);
58         mode = mode&~m;
59 }
60
61 const SockAddr &ClientSocket::get_peer_address() const
62 {
63         if(peer_addr==0)
64                 throw bad_socket_state("not connected");
65         return *peer_addr;
66 }
67
68 unsigned ClientSocket::do_write(const char *buf, unsigned size)
69 {
70         check_access(IO::M_WRITE);
71         if(!connected)
72                 throw bad_socket_state("not connected");
73
74         if(size==0)
75                 return 0;
76
77         int ret = ::send(priv->handle, buf, size, 0);
78         if(ret<0)
79         {
80                 if(errno==EAGAIN)
81                         return 0;
82                 else
83                         throw system_error("send");
84         }
85
86         return ret;
87 }
88
89 unsigned ClientSocket::do_read(char *buf, unsigned size)
90 {
91         check_access(IO::M_READ);
92         if(!connected)
93                 throw bad_socket_state("not connected");
94
95         if(size==0)
96                 return 0;
97
98         int ret = ::recv(priv->handle, buf, size, 0);
99         if(ret<0)
100         {
101                 if(errno==EAGAIN)
102                         return 0;
103                 else
104                         throw system_error("recv");
105         }
106         else if(ret==0 && !eof_flag)
107         {
108                 eof_flag = true;
109                 signal_end_of_file.emit();
110                 set_events(IO::P_NONE);
111         }
112
113         return ret;
114 }
115
116 } // namespace Net
117 } // namespace Msp