JackNetWinSocket.cpp 12.6 KB
Newer Older
1
/*
2
 Copyright (C) 2004-2008 Grame
3

4
5
6
7
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.
8

9
10
11
12
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.
13

14
15
16
 You should have received a copy of the GNU Lesser General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17

18
 */
19
20
21
22
23
24
25


#include "JackNetWinSocket.h"

namespace Jack
{
    //utility *********************************************************************************************************
26
    SERVER_EXPORT int GetHostName(char * name, int size)
27
    {
28
29
30
        if (gethostname(name, size) == SOCKET_ERROR) {
            jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
            strcpy(name, "default");
31
32
33
34
35
            return -1;
        }
        return 0;
    }

36
    win_net_error_t NetErrorList[] =
37
    {
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        E(0,                  "No error"),
        E(WSAEINTR,           "Interrupted system call"),
        E(WSAEBADF,           "Bad file number"),
        E(WSAEACCES,          "Permission denied"),
        E(WSAEFAULT,          "Bad address"),
        E(WSAEINVAL,          "Invalid argument"),
        E(WSAEMFILE,          "Too many open sockets"),
        E(WSAEWOULDBLOCK,     "Operation would block"),
        E(WSAEINPROGRESS,     "Operation now in progress"),
        E(WSAEALREADY,        "Operation already in progress"),
        E(WSAENOTSOCK,        "Socket operation on non-socket"),
        E(WSAEDESTADDRREQ,    "Destination address required"),
        E(WSAEMSGSIZE,        "Message too long"),
        E(WSAEPROTOTYPE,      "Protocol wrong type for socket"),
        E(WSAENOPROTOOPT,     "Bad protocol option"),
        E(WSAEPROTONOSUPPORT, "Protocol not supported"),
        E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
        E(WSAEOPNOTSUPP,      "Operation not supported on socket"),
        E(WSAEPFNOSUPPORT,    "Protocol family not supported"),
        E(WSAEAFNOSUPPORT,    "Address family not supported"),
        E(WSAEADDRINUSE,      "Address already in use"),
        E(WSAEADDRNOTAVAIL,   "Can't assign requested address"),
        E(WSAENETDOWN,        "Network is down"),
        E(WSAENETUNREACH,     "Network is unreachable"),
        E(WSAENETRESET,       "Net connection reset"),
        E(WSAECONNABORTED,    "Software caused connection abort"),
        E(WSAECONNRESET,      "Connection reset by peer"),
        E(WSAENOBUFS,         "No buffer space available"),
        E(WSAEISCONN,         "Socket is already connected"),
        E(WSAENOTCONN,        "Socket is not connected"),
        E(WSAESHUTDOWN,       "Can't send after socket shutdown"),
        E(WSAETOOMANYREFS,    "Too many references, can't splice"),
        E(WSAETIMEDOUT,       "Connection timed out"),
        E(WSAECONNREFUSED,    "Connection refused"),
        E(WSAELOOP,           "Too many levels of symbolic links"),
        E(WSAENAMETOOLONG,    "File name too long"),
        E(WSAEHOSTDOWN,       "Host is down"),
        E(WSAEHOSTUNREACH,    "No route to host"),
        E(WSAENOTEMPTY,       "Directory not empty"),
        E(WSAEPROCLIM,        "Too many processes"),
        E(WSAEUSERS,          "Too many users"),
        E(WSAEDQUOT,          "Disc quota exceeded"),
        E(WSAESTALE,          "Stale NFS file handle"),
        E(WSAEREMOTE,         "Too many levels of remote in path"),
        E(WSASYSNOTREADY,     "Network system is unavailable"),
        E(WSAVERNOTSUPPORTED, "Winsock version out of range"),
        E(WSANOTINITIALISED,  "WSAStartup not yet called"),
        E(WSAEDISCON,         "Graceful shutdown in progress"),
        E(WSAHOST_NOT_FOUND,  "Host not found"),
        E(WSANO_DATA,         "No host data of that type was found"),
88
89
90
        { -1, NULL },
    };

91
    SERVER_EXPORT const char* PrintError(int error)
92
93
    {
        int i;
94
95
        for (i = 0; NetErrorList[i].code >= 0; ++i) {
            if (error == NetErrorList[i].code)
96
                return NetErrorList[i].msg;
97
        }
98
        return strerror(error);
99
100
101
102
103
104
105
    }

    //construct/destruct***********************************************************************************************
    JackNetWinSocket::JackNetWinSocket()
    {
        fSockfd = 0;
        fSendAddr.sin_family = AF_INET;
106
107
        fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fSendAddr.sin_zero, 0, 8);
108
        fRecvAddr.sin_family = AF_INET;
109
110
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
111
112
    }

113
    JackNetWinSocket::JackNetWinSocket(const char* ip, int port)
114
115
116
117
    {
        fSockfd = 0;
        fPort = port;
        fSendAddr.sin_family = AF_INET;
118
119
120
        fSendAddr.sin_port = htons(port);
        fSendAddr.sin_addr.s_addr = inet_addr(ip);
        memset(&fSendAddr.sin_zero, 0, 8);
121
        fRecvAddr.sin_family = AF_INET;
122
123
124
        fRecvAddr.sin_port = htons(port);
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
125
126
    }

127
    JackNetWinSocket::JackNetWinSocket(const JackNetWinSocket& socket)
128
129
130
131
132
133
134
    {
        fSockfd = 0;
        fPort = socket.fPort;
        fSendAddr = socket.fSendAddr;
        fRecvAddr = socket.fRecvAddr;
    }

135
136
137
138
139
    JackNetWinSocket::~JackNetWinSocket()
    {
        Close();
    }

140
    JackNetWinSocket& JackNetWinSocket::operator=(const JackNetWinSocket& socket)
141
    {
142
        if (this != &socket) {
143
144
145
146
147
            fSockfd = 0;
            fPort = socket.fPort;
            fSendAddr = socket.fSendAddr;
            fRecvAddr = socket.fRecvAddr;
        }
148
        return *this;
149
150
    }

151
152
153
    //socket***********************************************************************************************************
    int JackNetWinSocket::NewSocket()
    {
154
        if (fSockfd) {
155
156
157
            Close();
            Reset();
        }
158
        fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
159
160
161
162
163
        return fSockfd;
    }

    int JackNetWinSocket::Bind()
    {
164
        return bind(fSockfd, reinterpret_cast<SOCKADDR*>(&fRecvAddr), sizeof(SOCKADDR));
165
166
    }

167
    int JackNetWinSocket::BindWith(const char* ip)
168
    {
169
        fRecvAddr.sin_addr.s_addr = inet_addr(ip);
170
171
172
        return Bind();
    }

173
    int JackNetWinSocket::BindWith(int port)
174
    {
175
        fRecvAddr.sin_port = htons(port);
176
177
178
179
180
        return Bind();
    }

    int JackNetWinSocket::Connect()
    {
181
        return connect(fSockfd, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
182
183
    }

184
    int JackNetWinSocket::ConnectTo(const char* ip)
185
    {
186
        fSendAddr.sin_addr.s_addr = inet_addr(ip);
187
188
189
190
191
        return Connect();
    }

    void JackNetWinSocket::Close()
    {
192
193
        if (fSockfd)
            closesocket(fSockfd);
194
195
196
197
198
199
        fSockfd = 0;
    }

    void JackNetWinSocket::Reset()
    {
        fSendAddr.sin_family = AF_INET;
200
201
202
        fSendAddr.sin_port = htons(fPort);
        fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fSendAddr.sin_zero, 0, 8);
203
        fRecvAddr.sin_family = AF_INET;
204
205
206
        fRecvAddr.sin_port = htons(fPort);
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
207
208
209
210
    }

    bool JackNetWinSocket::IsSocket()
    {
211
        return(fSockfd) ? true : false;
212
213
214
    }

    //IP/PORT***********************************************************************************************************
215
    void JackNetWinSocket::SetPort(int port)
216
217
    {
        fPort = port;
218
219
        fSendAddr.sin_port = htons(port);
        fRecvAddr.sin_port = htons(port);
220
221
222
223
224
225
226
227
    }

    int JackNetWinSocket::GetPort()
    {
        return fPort;
    }

    //address***********************************************************************************************************
228
    int JackNetWinSocket::SetAddress(const char* ip, int port)
229
    {
230
231
        fSendAddr.sin_addr.s_addr = inet_addr(ip);
        fSendAddr.sin_port = htons(port);
232
233
234
235
236
        return 0;
    }

    char* JackNetWinSocket::GetSendIP()
    {
237
        return inet_ntoa(fSendAddr.sin_addr);
238
239
240
241
    }

    char* JackNetWinSocket::GetRecvIP()
    {
242
        return inet_ntoa(fRecvAddr.sin_addr);
243
244
245
    }

    //utility************************************************************************************************************
246
    int JackNetWinSocket::GetName(char* name)
247
    {
248
        return gethostname(name, 255);
249
250
    }

251
    int JackNetWinSocket::JoinMCastGroup(const char* ip)
252
253
    {
        struct ip_mreq multicast_req;
254
255
        multicast_req.imr_multiaddr.s_addr = inet_addr(ip);
        multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
256
        //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...)
257
        return SetOption(IPPROTO_IP, 12, &multicast_req, sizeof(multicast_req));
258
259
260
    }

    //options************************************************************************************************************
261
    int JackNetWinSocket::SetOption(int level, int optname, const void* optval, SOCKLEN optlen)
262
    {
263
        return setsockopt(fSockfd, level, optname, static_cast<const char*>(optval), optlen);
264
265
    }

266
    int JackNetWinSocket::GetOption(int level, int optname, void* optval, SOCKLEN* optlen)
267
    {
268
        return getsockopt(fSockfd, level, optname, static_cast<char*>(optval), optlen);
269
270
271
    }

    //tiemout************************************************************************************************************
272
    int JackNetWinSocket::SetTimeOut(int usec)
273
    {
274
        jack_log("JackNetWinSocket::SetTimeout %d usec", usec);
moret's avatar
moret committed
275

276
        //negative timeout, or exceeding 10s, return
277
        if (( usec < 0) || (usec > 10000000))
278
            return SOCKET_ERROR;
279
        int time = usec / 1000;
280
        return SetOption(SOL_SOCKET, SO_RCVTIMEO, &time, sizeof(time));
281
282
283
284
285
    }

    //local loop*********************************************************************************************************
    int JackNetWinSocket::SetLocalLoop()
    {
286
287
288
289
290
291
        //char disable = 0;
        /*
        see http://msdn.microsoft.com/en-us/library/aa916098.aspx
        Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to
        which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer.
        */
292
        char disable = 1;
293
        return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
294
295
296
    }

    //network operations*************************************************************************************************
297
    int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags)
298
    {
299
        return sendto(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
300
301
    }

302
    int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
303
    {
304
305
        fSendAddr.sin_addr.s_addr = inet_addr(ip);
        return SendTo(buffer, nbytes, flags);
306
307
    }

308
    int JackNetWinSocket::Send(const void* buffer, size_t nbytes, int flags)
309
    {
310
        return send(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags);
311
312
    }

313
    int JackNetWinSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
314
    {
315
316
        SOCKLEN addr_len = sizeof(SOCKADDR);
        return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fRecvAddr), &addr_len);
317
318
    }

319
    int JackNetWinSocket::Recv(void* buffer, size_t nbytes, int flags)
320
    {
321
        return recv(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags);
322
323
    }

324
    int JackNetWinSocket::CatchHost(void* buffer, size_t nbytes, int flags)
325
    {
326
327
        SOCKLEN addr_len = sizeof(SOCKADDR);
        return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), &addr_len);
328
329
330
331
    }

    net_error_t JackNetWinSocket::GetError()
    {
332
        switch (NET_ERROR_CODE)
333
        {
moret's avatar
moret committed
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
            case WSABASEERR:
                return NET_NO_ERROR;
            case WSAETIMEDOUT:
                return NET_NO_DATA;
            case WSAEWOULDBLOCK:
                return NET_NO_DATA;
            case WSAECONNREFUSED:
                return NET_CONN_ERROR;
            case WSAECONNRESET:
                return NET_CONN_ERROR;
            case WSAEACCES:
                return NET_CONN_ERROR;
            case WSAECONNABORTED:
                return NET_CONN_ERROR;
            case WSAEHOSTDOWN:
                return NET_CONN_ERROR;
            case WSAEHOSTUNREACH:
                return NET_CONN_ERROR;
            default:
                return NET_OP_ERROR;
354
355
356
357
        }
    }
}