Jack2  1.9.9
JackNetWinSocket.cpp
1 /*
2  Copyright (C) 2004-2008 Grame
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as published by
6  the Free Software Foundation; either version 2.1 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
18  */
19 
20 #include "JackError.h"
21 #include "JackNetWinSocket.h"
22 
23 namespace Jack
24 {
25  //utility *********************************************************************************************************
26  SERVER_EXPORT int GetHostName(char * name, int size)
27  {
28  if (gethostname(name, size) == SOCKET_ERROR) {
29  jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
30  strcpy(name, "default");
31  return -1;
32  }
33  return 0;
34  }
35 
36  win_net_error_t NetErrorList[] =
37  {
38  E(0, "No error"),
39  E(WSAEINTR, "Interrupted system call"),
40  E(WSAEBADF, "Bad file number"),
41  E(WSAEACCES, "Permission denied"),
42  E(WSAEFAULT, "Bad address"),
43  E(WSAEINVAL, "Invalid argument"),
44  E(WSAEMFILE, "Too many open sockets"),
45  E(WSAEWOULDBLOCK, "Operation would block"),
46  E(WSAEINPROGRESS, "Operation now in progress"),
47  E(WSAEALREADY, "Operation already in progress"),
48  E(WSAENOTSOCK, "Socket operation on non-socket"),
49  E(WSAEDESTADDRREQ, "Destination address required"),
50  E(WSAEMSGSIZE, "Message too long"),
51  E(WSAEPROTOTYPE, "Protocol wrong type for socket"),
52  E(WSAENOPROTOOPT, "Bad protocol option"),
53  E(WSAEPROTONOSUPPORT, "Protocol not supported"),
54  E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
55  E(WSAEOPNOTSUPP, "Operation not supported on socket"),
56  E(WSAEPFNOSUPPORT, "Protocol family not supported"),
57  E(WSAEAFNOSUPPORT, "Address family not supported"),
58  E(WSAEADDRINUSE, "Address already in use"),
59  E(WSAEADDRNOTAVAIL, "Can't assign requested address"),
60  E(WSAENETDOWN, "Network is down"),
61  E(WSAENETUNREACH, "Network is unreachable"),
62  E(WSAENETRESET, "Net connection reset"),
63  E(WSAECONNABORTED, "Software caused connection abort"),
64  E(WSAECONNRESET, "Connection reset by peer"),
65  E(WSAENOBUFS, "No buffer space available"),
66  E(WSAEISCONN, "Socket is already connected"),
67  E(WSAENOTCONN, "Socket is not connected"),
68  E(WSAESHUTDOWN, "Can't send after socket shutdown"),
69  E(WSAETOOMANYREFS, "Too many references, can't splice"),
70  E(WSAETIMEDOUT, "Connection timed out"),
71  E(WSAECONNREFUSED, "Connection refused"),
72  E(WSAELOOP, "Too many levels of symbolic links"),
73  E(WSAENAMETOOLONG, "File name too long"),
74  E(WSAEHOSTDOWN, "Host is down"),
75  E(WSAEHOSTUNREACH, "No route to host"),
76  E(WSAENOTEMPTY, "Directory not empty"),
77  E(WSAEPROCLIM, "Too many processes"),
78  E(WSAEUSERS, "Too many users"),
79  E(WSAEDQUOT, "Disc quota exceeded"),
80  E(WSAESTALE, "Stale NFS file handle"),
81  E(WSAEREMOTE, "Too many levels of remote in path"),
82  E(WSASYSNOTREADY, "Network system is unavailable"),
83  E(WSAVERNOTSUPPORTED, "Winsock version out of range"),
84  E(WSANOTINITIALISED, "WSAStartup not yet called"),
85  E(WSAEDISCON, "Graceful shutdown in progress"),
86  E(WSAHOST_NOT_FOUND, "Host not found"),
87  E(WSANO_DATA, "No host data of that type was found"),
88  { -1, NULL },
89  };
90 
91  SERVER_EXPORT const char* PrintError(int error)
92  {
93  int i;
94  for (i = 0; NetErrorList[i].code >= 0; ++i) {
95  if (error == NetErrorList[i].code)
96  return NetErrorList[i].msg;
97  }
98  return strerror(error);
99  }
100 
101  //construct/destruct***********************************************************************************************
102  JackNetWinSocket::JackNetWinSocket()
103  {
104  fSockfd = 0;
105  fSendAddr.sin_family = AF_INET;
106  fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
107  memset(&fSendAddr.sin_zero, 0, 8);
108  fRecvAddr.sin_family = AF_INET;
109  fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
110  memset(&fRecvAddr.sin_zero, 0, 8);
111  }
112 
113  JackNetWinSocket::JackNetWinSocket(const char* ip, int port)
114  {
115  fSockfd = 0;
116  fPort = port;
117  fSendAddr.sin_family = AF_INET;
118  fSendAddr.sin_port = htons(port);
119  fSendAddr.sin_addr.s_addr = inet_addr(ip);
120  memset(&fSendAddr.sin_zero, 0, 8);
121  fRecvAddr.sin_family = AF_INET;
122  fRecvAddr.sin_port = htons(port);
123  fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
124  memset(&fRecvAddr.sin_zero, 0, 8);
125  }
126 
127  JackNetWinSocket::JackNetWinSocket(const JackNetWinSocket& socket)
128  {
129  fSockfd = 0;
130  fPort = socket.fPort;
131  fSendAddr = socket.fSendAddr;
132  fRecvAddr = socket.fRecvAddr;
133  }
134 
135  JackNetWinSocket::~JackNetWinSocket()
136  {
137  Close();
138  }
139 
140  JackNetWinSocket& JackNetWinSocket::operator=(const JackNetWinSocket& socket)
141  {
142  if (this != &socket) {
143  fSockfd = 0;
144  fPort = socket.fPort;
145  fSendAddr = socket.fSendAddr;
146  fRecvAddr = socket.fRecvAddr;
147  }
148  return *this;
149  }
150 
151  //socket***********************************************************************************************************
152  int JackNetWinSocket::NewSocket()
153  {
154  if (fSockfd) {
155  Close();
156  Reset();
157  }
158  fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
159  return fSockfd;
160  }
161 
162  bool JackNetWinSocket::IsLocal(char* ip)
163  {
164  if (strcmp(ip, "127.0.0.1") == 0) {
165  return true;
166  }
167 
168  char host_name[32];
169  gethostname(host_name, sizeof(host_name));
170 
171  struct hostent* host = gethostbyname(host_name);
172  if (host) {
173  for (int i = 0; host->h_addr_list[i] != 0; ++i) {
174  struct in_addr addr;
175  memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
176  if (strcmp(inet_ntoa(addr), ip) == 0) {
177  return true;
178  }
179  }
180  return false;
181  } else {
182  return false;
183  }
184  }
185 
186  int JackNetWinSocket::Bind()
187  {
188  return bind(fSockfd, reinterpret_cast<SOCKADDR*>(&fRecvAddr), sizeof(SOCKADDR));
189  }
190 
191  int JackNetWinSocket::BindWith(const char* ip)
192  {
193  fRecvAddr.sin_addr.s_addr = inet_addr(ip);
194  return Bind();
195  }
196 
197  int JackNetWinSocket::BindWith(int port)
198  {
199  fRecvAddr.sin_port = htons(port);
200  return Bind();
201  }
202 
203  int JackNetWinSocket::Connect()
204  {
205  return connect(fSockfd, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
206  }
207 
208  int JackNetWinSocket::ConnectTo(const char* ip)
209  {
210  fSendAddr.sin_addr.s_addr = inet_addr(ip);
211  return Connect();
212  }
213 
214  void JackNetWinSocket::Close()
215  {
216  if (fSockfd)
217  closesocket(fSockfd);
218  fSockfd = 0;
219  }
220 
221  void JackNetWinSocket::Reset()
222  {
223  fSendAddr.sin_family = AF_INET;
224  fSendAddr.sin_port = htons(fPort);
225  fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
226  memset(&fSendAddr.sin_zero, 0, 8);
227  fRecvAddr.sin_family = AF_INET;
228  fRecvAddr.sin_port = htons(fPort);
229  fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
230  memset(&fRecvAddr.sin_zero, 0, 8);
231  }
232 
233  bool JackNetWinSocket::IsSocket()
234  {
235  return(fSockfd) ? true : false;
236  }
237 
238  //IP/PORT***********************************************************************************************************
239  void JackNetWinSocket::SetPort(int port)
240  {
241  fPort = port;
242  fSendAddr.sin_port = htons(port);
243  fRecvAddr.sin_port = htons(port);
244  }
245 
246  int JackNetWinSocket::GetPort()
247  {
248  return fPort;
249  }
250 
251  //address***********************************************************************************************************
252  int JackNetWinSocket::SetAddress(const char* ip, int port)
253  {
254  fSendAddr.sin_addr.s_addr = inet_addr(ip);
255  fSendAddr.sin_port = htons(port);
256  return 0;
257  }
258 
259  char* JackNetWinSocket::GetSendIP()
260  {
261  return inet_ntoa(fSendAddr.sin_addr);
262  }
263 
264  char* JackNetWinSocket::GetRecvIP()
265  {
266  return inet_ntoa(fRecvAddr.sin_addr);
267  }
268 
269  //utility************************************************************************************************************
270  int JackNetWinSocket::GetName(char* name)
271  {
272  return gethostname(name, 255);
273  }
274 
275  int JackNetWinSocket::JoinMCastGroup(const char* ip)
276  {
277  struct ip_mreq multicast_req;
278  multicast_req.imr_multiaddr.s_addr = inet_addr(ip);
279  multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
280  //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...)
281  return SetOption(IPPROTO_IP, 12, &multicast_req, sizeof(multicast_req));
282  }
283 
284  //options************************************************************************************************************
285  int JackNetWinSocket::SetOption(int level, int optname, const void* optval, SOCKLEN optlen)
286  {
287  return setsockopt(fSockfd, level, optname, static_cast<const char*>(optval), optlen);
288  }
289 
290  int JackNetWinSocket::GetOption(int level, int optname, void* optval, SOCKLEN* optlen)
291  {
292  return getsockopt(fSockfd, level, optname, static_cast<char*>(optval), optlen);
293  }
294 
295  //tiemout************************************************************************************************************
296  int JackNetWinSocket::SetTimeOut(int usec)
297  {
298  jack_log("JackNetWinSocket::SetTimeout %d usec", usec);
299  int millisec = usec / 1000;
300  return SetOption(SOL_SOCKET, SO_RCVTIMEO, &millisec, sizeof(millisec));
301  }
302 
303  //local loop*********************************************************************************************************
304  int JackNetWinSocket::SetLocalLoop()
305  {
306  //char disable = 0;
307  /*
308  see http://msdn.microsoft.com/en-us/library/aa916098.aspx
309  Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to
310  which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer.
311  */
312  char disable = 1;
313  return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
314  }
315 
316  //network operations*************************************************************************************************
317  int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags)
318  {
319  return sendto(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
320  }
321 
322  int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
323  {
324  fSendAddr.sin_addr.s_addr = inet_addr(ip);
325  return SendTo(buffer, nbytes, flags);
326  }
327 
328  int JackNetWinSocket::Send(const void* buffer, size_t nbytes, int flags)
329  {
330  return send(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags);
331  }
332 
333  int JackNetWinSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
334  {
335  SOCKLEN addr_len = sizeof(SOCKADDR);
336  return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fRecvAddr), &addr_len);
337  }
338 
339  int JackNetWinSocket::Recv(void* buffer, size_t nbytes, int flags)
340  {
341  return recv(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags);
342  }
343 
344  int JackNetWinSocket::CatchHost(void* buffer, size_t nbytes, int flags)
345  {
346  SOCKLEN addr_len = sizeof(SOCKADDR);
347  return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), &addr_len);
348  }
349 
350  net_error_t JackNetWinSocket::GetError()
351  {
352  switch (NET_ERROR_CODE)
353  {
354  case WSABASEERR:
355  return NET_NO_ERROR;
356  case WSAETIMEDOUT:
357  return NET_NO_DATA;
358  case WSAEWOULDBLOCK:
359  return NET_NO_DATA;
360  case WSAECONNREFUSED:
361  return NET_CONN_ERROR;
362  case WSAECONNRESET:
363  return NET_CONN_ERROR;
364  case WSAEACCES:
365  return NET_CONN_ERROR;
366  case WSAECONNABORTED:
367  return NET_CONN_ERROR;
368  case WSAEHOSTDOWN:
369  return NET_CONN_ERROR;
370  case WSAEHOSTUNREACH:
371  return NET_CONN_ERROR;
372  default:
373  return NET_OP_ERROR;
374  }
375  }
376 }
377 
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107