0b11c590420e566f00e8c886a76d79a646715d8f
[deb_libcec.git] / src / lib / platform / windows / os-socket.h
1 #pragma once
2 /*
3 * This file is part of the libCEC(R) library.
4 *
5 * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
6 * libCEC(R) is an original work, containing original code.
7 *
8 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 *
10 * This program is dual-licensed; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 *
25 * Alternatively, you can license this library under a commercial license,
26 * please contact Pulse-Eight Licensing for more information.
27 *
28 * For more information contact:
29 * Pulse-Eight Licensing <license@pulse-eight.com>
30 * http://www.pulse-eight.com/
31 * http://www.pulse-eight.net/
32 */
33
34 #include "../os.h"
35 #include "../util/timeutils.h"
36
37 #pragma comment(lib, "Ws2_32.lib")
38 #include <ws2spi.h>
39 #include <ws2ipdef.h>
40 #include <ws2tcpip.h>
41
42 #define SHUT_RDWR SD_BOTH
43
44 #ifndef ETIMEDOUT
45 #define ETIMEDOUT 138
46 #endif
47
48 namespace PLATFORM
49 {
50 #ifndef MSG_WAITALL
51 #define MSG_WAITALL 0x8
52 #endif
53
54 inline int GetSocketError(void)
55 {
56 int error = WSAGetLastError();
57 switch(error)
58 {
59 case WSAEINPROGRESS: return EINPROGRESS;
60 case WSAECONNRESET : return ECONNRESET;
61 case WSAETIMEDOUT : return ETIMEDOUT;
62 case WSAEWOULDBLOCK: return EAGAIN;
63 default : return error;
64 }
65 }
66
67 inline void SocketClose(socket_t socket)
68 {
69 if (socket != SOCKET_ERROR && socket != INVALID_SOCKET)
70 closesocket(socket);
71 }
72
73 inline void SocketSetBlocking(socket_t socket, bool bSetTo)
74 {
75 u_long nVal = bSetTo ? 1 : 0;
76 ioctlsocket(socket, FIONBIO, &nVal);
77 }
78
79 inline int64_t SocketWrite(socket_t socket, int *iError, uint8_t* data, uint32_t len)
80 {
81 int64_t iReturn(-1);
82 if (socket != SOCKET_ERROR && socket != INVALID_SOCKET)
83 {
84 iReturn = send(socket, (char*)data, len, 0);
85 if (iReturn <= 0)
86 *iError = GetSocketError();
87 }
88 return iReturn;
89 }
90
91 inline int SocketReadFixed(socket_t socket, char *buf, int iLength, int iFlags)
92 {
93 char* org = buf;
94 int nRes = 1;
95
96 if ((iFlags & MSG_WAITALL) == 0)
97 return recv(socket, buf, iLength, iFlags);
98
99 iFlags &= ~MSG_WAITALL;
100 while(iLength > 0 && nRes > 0)
101 {
102 nRes = recv(socket, buf, iLength, iFlags);
103 if (nRes < 0)
104 return nRes;
105
106 buf += nRes;
107 iLength -= nRes;
108 }
109 return buf - org;
110 }
111
112 inline int32_t SocketRead(socket_t socket, void *buf, uint32_t nLen)
113 {
114 int x = SocketReadFixed(socket, (char *)buf, nLen, MSG_WAITALL);
115
116 if (x == -1)
117 return GetSocketError();
118 if (x != (int)nLen)
119 return ECONNRESET;
120
121 return 0;
122 }
123
124 inline int32_t SocketRead(socket_t socket, int *iError, uint8_t* data, uint32_t iLength, uint64_t iTimeoutMs)
125 {
126 int x, tot = 0, nErr;
127 fd_set fd_read;
128 struct timeval tv;
129
130 if (iTimeoutMs <= 0)
131 return EINVAL;
132
133 while(tot != (int)iLength)
134 {
135 tv.tv_sec = (long)(iTimeoutMs / 1000);
136 tv.tv_usec = (long)(1000 * (iTimeoutMs % 1000));
137
138 FD_ZERO(&fd_read);
139 FD_SET(socket, &fd_read);
140
141 x = select(socket + 1, &fd_read, NULL, NULL, &tv);
142
143 if (x == 0)
144 return ETIMEDOUT;
145
146 SocketSetBlocking(socket, false);
147
148 x = SocketReadFixed(socket, (char *)data + tot, iLength - tot, 0);
149 nErr = GetSocketError();
150
151 SocketSetBlocking(socket, true);
152
153 if (x == -1)
154 {
155 if (nErr == EAGAIN)
156 continue;
157 return nErr;
158 }
159
160 if (x == 0)
161 return ECONNRESET;
162
163 tot += x;
164 }
165 return 0;
166 }
167 }