8 // Debug printing options
12 bool g_sockets_initialized = false;
18 if(WSAStartup( MAKEWORD(2,2), &WsaData ) != NO_ERROR)
19 throw SocketException("WSAStartup failed");
22 g_sockets_initialized = true;
25 void sockets_cleanup()
36 Address::Address(unsigned int address, unsigned short port)
42 Address::Address(unsigned int a, unsigned int b,
43 unsigned int c, unsigned int d,
46 m_address = (a<<24) | (b<<16) | ( c<<8) | d;
50 bool Address::operator==(Address &address)
52 return (m_address == address.m_address
53 && m_port == address.m_port);
56 bool Address::operator!=(Address &address)
58 return !(*this == address);
61 void Address::Resolve(const char *name)
63 struct addrinfo *resolved;
64 int e = getaddrinfo(name, NULL, NULL, &resolved);
66 throw ResolveError("");
68 FIXME: This is an ugly hack; change the whole class
69 to store the address as sockaddr
71 struct sockaddr_in *t = (struct sockaddr_in*)resolved->ai_addr;
72 m_address = ntohl(t->sin_addr.s_addr);
73 freeaddrinfo(resolved);
76 unsigned int Address::getAddress() const
81 unsigned short Address::getPort() const
86 void Address::setAddress(unsigned int address)
91 void Address::setPort(unsigned short port)
96 void Address::print(std::ostream *s) const
98 (*s)<<((m_address>>24)&0xff)<<"."
99 <<((m_address>>16)&0xff)<<"."
100 <<((m_address>>8)&0xff)<<"."
101 <<((m_address>>0)&0xff)<<":"
105 void Address::print() const
110 UDPSocket::UDPSocket()
112 if(g_sockets_initialized == false)
113 throw SocketException("Sockets not initialized");
115 m_handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
118 dstream<<DPS<<"UDPSocket("<<(int)m_handle<<")::UDPSocket()"<<std::endl;
122 throw SocketException("Failed to create socket");
126 DWORD nonblocking = 0;
127 if(ioctlsocket(m_handle, FIONBIO, &nonblocking) != 0)
129 throw SocketException("Failed set non-blocking mode");
133 if(fcntl(m_handle, F_SETFL, O_NONBLOCK, nonblocking) == -1)
135 throw SocketException("Failed set non-blocking mode");
142 UDPSocket::~UDPSocket()
145 dstream<<DPS<<"UDPSocket("<<(int)m_handle<<")::~UDPSocket()"<<std::endl;
148 closesocket(m_handle);
154 void UDPSocket::Bind(unsigned short port)
157 dstream<<DPS<<"UDPSocket("<<(int)m_handle
158 <<")::Bind(): port="<<port<<std::endl;
161 address.sin_family = AF_INET;
162 address.sin_addr.s_addr = INADDR_ANY;
163 address.sin_port = htons(port);
165 if(bind(m_handle, (const sockaddr*)&address, sizeof(sockaddr_in)) < 0)
167 #ifndef DISABLE_ERRNO
168 dstream<<(int)m_handle<<": Bind failed: "<<strerror(errno)<<std::endl;
170 throw SocketException("Failed to bind socket");
174 void UDPSocket::Send(const Address & destination, const void * data, int size)
176 bool dumping_packet = false;
177 if(INTERNET_SIMULATOR)
178 dumping_packet = (rand()%10==0); //easy
179 //dumping_packet = (rand()%4==0); // hard
182 /*dstream<<DPS<<"UDPSocket("<<(int)m_handle
183 <<")::Send(): destination=";*/
185 dstream<<(int)m_handle<<" -> ";
187 dstream<<", size="<<size<<", data=";
188 for(int i=0; i<size && i<20; i++){
189 if(i%2==0) printf(" ");
190 DEBUGPRINT("%.2X", ((int)((const char*)data)[i])&0xff);
195 dstream<<" (DUMPED BY INTERNET_SIMULATOR)";
198 else if(dumping_packet)
200 // Lol let's forget it
201 dstream<<"UDPSocket::Send(): "
202 "INTERNET_SIMULATOR: dumping packet."
210 address.sin_family = AF_INET;
211 address.sin_addr.s_addr = htonl(destination.getAddress());
212 address.sin_port = htons(destination.getPort());
214 int sent = sendto(m_handle, (const char*)data, size,
215 0, (sockaddr*)&address, sizeof(sockaddr_in));
219 throw SendFailedException("Failed to send packet");
223 int UDPSocket::Receive(Address & sender, void * data, int size)
225 if(WaitData(m_timeout_ms) == false)
231 socklen_t address_len = sizeof(address);
233 int received = recvfrom(m_handle, (char*)data,
234 size, 0, (sockaddr*)&address, &address_len);
239 unsigned int address_ip = ntohl(address.sin_addr.s_addr);
240 unsigned int address_port = ntohs(address.sin_port);
242 sender = Address(address_ip, address_port);
245 //dstream<<DPS<<"UDPSocket("<<(int)m_handle<<")::Receive(): sender=";
246 dstream<<DPS<<(int)m_handle<<" <- ";
248 //dstream<<", received="<<received<<std::endl;
249 dstream<<", size="<<received<<", data=";
250 for(int i=0; i<received && i<20; i++){
251 if(i%2==0) printf(" ");
252 DEBUGPRINT("%.2X", ((int)((const char*)data)[i])&0xff);
262 int UDPSocket::GetHandle()
267 void UDPSocket::setTimeoutMs(int timeout_ms)
269 m_timeout_ms = timeout_ms;
272 bool UDPSocket::WaitData(int timeout_ms)
277 // Initialize the set
279 FD_SET(m_handle, &readset);
281 // Initialize time out struct
284 tv.tv_usec = timeout_ms * 1000;
286 result = select(m_handle+1, &readset, NULL, NULL, &tv);
290 /*dstream<<"Select timed out (timeout_ms="
291 <<timeout_ms<<")"<<std::endl;*/
296 #ifndef DISABLE_ERRNO
297 dstream<<(int)m_handle<<": Select failed: "<<strerror(errno)<<std::endl;
300 int e = WSAGetLastError();
301 dstream<<(int)m_handle<<": WSAGetLastError()="<<e<<std::endl;
302 if(e == 10004 /*=WSAEINTR*/)
304 dstream<<"WARNING: Ignoring WSAEINTR."<<std::endl;
308 throw SocketException("Select failed");
310 else if(FD_ISSET(m_handle, &readset) == false){
312 //dstream<<"Select reported no data in m_handle"<<std::endl;
317 //dstream<<"Select reported data in m_handle"<<std::endl;