3 This file is part of libmspnet
4 Copyright © 2008-2009 Mikkosoft Productions, Mikko Rasa
5 Distributed under the LGPL
9 #include <sys/socket.h>
12 #include <msp/io/poll.h>
13 #include <msp/strings/formatter.h>
14 #include "streamsocket.h"
20 Used by StreamListenSocket to construct a new socket from accept.
22 StreamSocket::StreamSocket(SocketHandle h, const SockAddr &paddr):
27 WSAEventSelect(handle, event, FD_READ|FD_CLOSE);
29 set_events(IO::P_INPUT);
33 Constructs a new StreamSocket.
35 StreamSocket::StreamSocket(Family af, int proto):
36 Socket(af, SOCK_STREAM, proto),
41 Checks the status of an ongoing connection attempt. If the connection fails
42 with an error, an exception is thrown.
44 @return 0 if the connection finished, 1 if not
46 int StreamSocket::poll_connect(const Time::TimeDelta &timeout)
50 throw InvalidState("No connection attempt going on");
52 int res=poll(*this, IO::P_OUTPUT, timeout);
55 throw Exception(format("Connection polling failed: %d", WSAGetLastError()));
57 throw SystemError("Connection polling failed", errno);
64 socklen_t len=sizeof(int);
65 get_option(SOL_SOCKET, SO_ERROR, &err, &len);
69 set_events(IO::P_NONE);
71 throw Exception(format("Connection failed: %d", err));
73 throw SystemError("Connection failed", err);
78 WSAEventSelect(handle, event, FD_READ|FD_CLOSE);
80 set_events(IO::P_INPUT);
91 Connects the socket to a remote address. In non-blocking mode, this function
92 may return before the connection is finished. The caller must then use either
93 the poll_connect function or an EventDispatcher to determine when the
94 connection is finished.
96 @return 0 if the connection finished, 1 if it is in progress
98 int StreamSocket::connect(const SockAddr &addr)
103 throw InvalidState("Socket is already connected");
106 socklen_t size=addr.fill_sockaddr(sa);
109 int err=WSAConnect(handle, &sa, size, 0, 0, 0, 0);
110 if(err==SOCKET_ERROR)
112 int err_code=WSAGetLastError();
113 if(err_code==WSAEWOULDBLOCK)
116 WSAEventSelect(handle, event, FD_CONNECT);
117 set_events(IO::P_OUTPUT);
120 throw Exception(format("Unable to connect: %d", err_code));
123 int err=::connect(handle, &sa, size);
126 if(errno==EINPROGRESS)
129 set_events(IO::P_OUTPUT);
132 throw SystemError("Unable to connect", errno);
137 peer_addr=addr.copy();
140 size=sizeof(sockaddr);
141 getsockname(handle, &sa, &size);
142 local_addr=SockAddr::create(sa);
147 set_events(IO::P_INPUT);
148 signal_connect_finished.emit(0);
154 void StreamSocket::on_event(IO::PollEvent ev)
156 //cout<<"StreamSocket::on_event "<<ev<<'\n';
157 if((ev&(IO::P_OUTPUT|IO::P_ERROR)) && connecting)
160 socklen_t len=sizeof(err);
161 get_option(SOL_SOCKET, SO_ERROR, &err, &len);
165 signal_connect_finished.emit(err);
174 WSAEventSelect(handle, event, FD_READ|FD_CLOSE);
176 set_events((err==0) ? IO::P_INPUT : IO::P_NONE);