]> git.sesse.net Git - vlc/blob - src/win32/winsock.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / src / win32 / winsock.c
1 /*****************************************************************************
2  * winsock.c: POSIX replacements for Winsock
3  *****************************************************************************
4  * Copyright © 2006-2008 Rémi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <vlc_common.h>
26 #include <errno.h>
27 #include <vlc_network.h>
28
29 #ifndef WSA_QOS_EUNKNOWNPSOBJ
30 # define WSA_QOS_EUNKNOWNPSOBJ 11024L
31 #endif
32
33 typedef struct
34 {
35     int code;
36     const char *msg;
37 } wsaerrmsg_t;
38
39 static const wsaerrmsg_t wsaerrmsg[] =
40 {
41     { WSA_INVALID_HANDLE, "Specified event object handle is invalid" },
42     { WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available" },
43     { WSA_INVALID_PARAMETER, "One or more parameters are invalid" },
44     { WSA_OPERATION_ABORTED, "Overlapped operation aborted" },
45     { WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state" },
46     { WSA_IO_PENDING, "Overlapped operations will complete later" },
47     { WSAEINTR, "Interrupted function call" },
48     { WSAEBADF, "File handle is not valid" },
49     { WSAEACCES, "Access denied" },
50     { WSAEFAULT, "Invalid memory address" },
51     { WSAEINVAL, "Invalid argument" },
52     { WSAEMFILE, "Too many open sockets" },
53     { WSAEWOULDBLOCK, "Resource temporarily unavailable" },
54     { WSAEINPROGRESS, "Operation now in progress" },
55     { WSAEALREADY, "Operation already in progress" },
56     { WSAENOTSOCK, "Non-socket handle specified" },
57     { WSAEDESTADDRREQ, "Missing destination address" },
58     { WSAEMSGSIZE, "Message too long" },
59     { WSAEPROTOTYPE, "Protocol wrong type for socket", },
60     { WSAENOPROTOOPT, "Option not supported by protocol" },
61     { WSAEPROTONOSUPPORT, "Protocol not supported" },
62     { WSAESOCKTNOSUPPORT, "Socket type not supported" },
63     { WSAEOPNOTSUPP, "Operation not supported" },
64     { WSAEPFNOSUPPORT, "Protocol family not supported" },
65     { WSAEAFNOSUPPORT, "Address family not supported by protocol family" },
66     { WSAEADDRINUSE, "Address already in use" },
67     { WSAEADDRNOTAVAIL, "Cannot assign requested address" },
68     { WSAENETDOWN, "Network is down" },
69     { WSAENETUNREACH, "Network unreachable" },
70     { WSAENETRESET, "Network dropped connection on reset" },
71     { WSAECONNABORTED, "Software caused connection abort" },
72     { WSAECONNRESET, "Connection reset by peer" },
73     { WSAENOBUFS, "No buffer space available (not enough memory)" },
74     { WSAEISCONN, "Socket is already connected" },
75     { WSAENOTCONN, "Socket is not connected" },
76     { WSAESHUTDOWN, "Cannot send after socket shutdown" },
77     { WSAETOOMANYREFS, "Too many references" },
78     { WSAETIMEDOUT, "Connection timed out" },
79     { WSAECONNREFUSED, "Connection refused by peer" },
80     { WSAELOOP, "Cannot translate name" },
81     { WSAENAMETOOLONG, "Name too long" },
82     { WSAEHOSTDOWN, "Remote host is down" },
83     { WSAEHOSTUNREACH, "No route to host (unreachable)" },
84     { WSAENOTEMPTY, "Directory not empty" },
85     { WSAEPROCLIM, "Too many processes" },
86     { WSAEUSERS, "User quota exceeded" },
87     { WSAEDQUOT, "Disk quota exceeded" },
88     { WSAESTALE, "Stale file handle reference" },
89     { WSAEREMOTE, "Item is remote", },
90     { WSASYSNOTREADY, "Network subsystem is unavailable (network stack not ready)" },
91     { WSAVERNOTSUPPORTED, "Winsock.dll version out of range (network stack version not supported" },
92     { WSANOTINITIALISED, "Network not initialized" },
93     { WSAEDISCON, "Graceful shutdown in progress" },
94     { WSAENOMORE, "No more results" },
95     { WSAECANCELLED, "Call has been cancelled" },
96     { WSAEINVALIDPROCTABLE, "Procedure call table is invalid" },
97     { WSAEINVALIDPROVIDER, "Service provider is invalid" },
98     { WSAEPROVIDERFAILEDINIT, "Service provider failed to initialize" },
99     { WSASYSCALLFAILURE, "System call failure" },
100     { WSASERVICE_NOT_FOUND, "Service not found" },
101     { WSATYPE_NOT_FOUND, "Class type not found" },
102     { WSA_E_NO_MORE, "No more results" },
103     { WSA_E_CANCELLED, "Call was cancelled" },
104     { WSAEREFUSED, "Database query was refused" },
105     { WSAHOST_NOT_FOUND, "Host not found" },
106     { WSATRY_AGAIN, "Nonauthoritative host not found (temporary hostname error)" },
107     { WSANO_RECOVERY, "Non-recoverable hostname error" },
108     { WSANO_DATA, "Valid name, no data record of requested type" },
109     { WSA_QOS_RECEIVERS, "QOS receivers" },
110     { WSA_QOS_SENDERS, "QOS senders" },
111     { WSA_QOS_NO_SENDERS, "No QOS senders" },
112     { WSA_QOS_NO_RECEIVERS, "QOS no receivers" },
113     { WSA_QOS_REQUEST_CONFIRMED, "QOS request confirmed" },
114     { WSA_QOS_ADMISSION_FAILURE, "QOS admission error" },
115     { WSA_QOS_POLICY_FAILURE, "QOS policy failure" },
116     { WSA_QOS_BAD_STYLE, "QOS bad style" },
117     { WSA_QOS_BAD_OBJECT, "QOS bad object" },
118     { WSA_QOS_TRAFFIC_CTRL_ERROR, "QOS traffic control error" },
119     { WSA_QOS_GENERIC_ERROR, "QOS generic error" },
120     { WSA_QOS_ESERVICETYPE, "QOS service type error" },
121     { WSA_QOS_EFLOWSPEC, "QOS flowspec error" },
122     { WSA_QOS_EPROVSPECBUF, "Invalid QOS provider buffer" },
123     { WSA_QOS_EFILTERSTYLE, "Invalid QOS filter style" },
124     { WSA_QOS_EFILTERTYPE, "Invalid QOS filter type" },
125     { WSA_QOS_EFILTERCOUNT, "Incorrect QOS filter count" },
126     { WSA_QOS_EOBJLENGTH, "Invalid QOS object length" },
127     { WSA_QOS_EFLOWCOUNT, "Incorrect QOS flow count" },
128     { WSA_QOS_EUNKNOWNPSOBJ, "Unrecognized QOS object" },
129     { WSA_QOS_EPOLICYOBJ, "Invalid QOS policy object" },
130     { WSA_QOS_EFLOWDESC, "Invalid QOS flow descriptor" },
131     { WSA_QOS_EPSFLOWSPEC, "Invalid QOS provider-specific flowspec" },
132     { WSA_QOS_EPSFILTERSPEC, "Invalid QOS provider-specific filterspec" },
133     { WSA_QOS_ESDMODEOBJ, "Invalid QOS shape discard mode object" },
134     { WSA_QOS_ESHAPERATEOBJ, "Invalid QOS shaping rate object" },
135     { WSA_QOS_RESERVED_PETYPE, "Reserved policy QOS element type" },
136     { 0, NULL }
137     /* Winsock2 error codes are missing, they "never" occur */
138 };
139
140
141 const char *net_strerror( int value )
142 {
143     /* There doesn't seem to be any portable error message generation for
144      * Winsock errors. Some old versions had s_error, but it appears to be
145      * gone, and is not documented.
146      */
147     for( const wsaerrmsg_t *e = wsaerrmsg; e->msg != NULL; e++ )
148         if( e->code == value )
149             return e->msg;
150
151     /* Remember to update src/misc/messages.c if you change this one */
152     return "Unknown network stack error";
153 }
154
155 #if 0
156 ssize_t vlc_sendmsg (int s, struct msghdr *hdr, int flags)
157 {
158     /* WSASendMsg would be more straightforward, and would support ancilliary
159      * data, but it's not yet in mingw32. */
160     if ((hdr->msg_iovlen > 100) || (hdr->msg_controllen > 0))
161     {
162         errno = EINVAL;
163         return -1;
164     }
165
166     WSABUF buf[hdr->msg_iovlen];
167     for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
168         buf[i].buf = hdr->msg_iov[i].iov_base,
169         buf[i].len = hdr->msg_iov[i].iov_len;
170
171     DWORD sent;
172     if (WSASendTo (s, buf, sizeof (buf) / sizeof (buf[0]), &sent, flags,
173                    hdr->msg_name, hdr->msg_namelen, NULL, NULL) == 0)
174         return sent;
175     return -1;
176 }
177
178 ssize_t vlc_recvmsg (int s, struct msghdr *hdr, int flags)
179 {
180     /* WSARecvMsg would be more straightforward, and would support ancilliary
181      * data, but it's not yet in mingw32. */
182     if (hdr->msg_iovlen > 100)
183     {
184         errno = EINVAL;
185         return -1;
186     }
187
188     WSABUF buf[hdr->msg_iovlen];
189     for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
190         buf[i].buf = hdr->msg_iov[i].iov_base,
191         buf[i].len = hdr->msg_iov[i].iov_len;
192
193     DWORD recvd, dwFlags = flags;
194     INT fromlen = hdr->msg_namelen;
195     hdr->msg_controllen = 0;
196     hdr->msg_flags = 0;
197
198     int ret = WSARecvFrom (s, buf, sizeof (buf) / sizeof (buf[0]), &recvd,
199                            &dwFlags, hdr->msg_name, &fromlen, NULL, NULL);
200     hdr->msg_namelen = fromlen;
201     hdr->msg_flags = dwFlags;
202     if (ret == 0)
203         return recvd;
204
205 #ifdef MSG_TRUNC
206     if (WSAGetLastError() == WSAEMSGSIZE)
207     {
208         hdr->msg_flags |= MSG_TRUNC;
209         return recvd;
210     }
211 #else
212 # warning Out-of-date Winsock header files!
213 #endif
214     return -1;
215 }
216 #endif