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 dstream<<(int)m_handle<<": Bind failed: "<<strerror(errno)<<std::endl;
168 throw SocketException("Failed to bind socket");
172 void UDPSocket::Send(const Address & destination, const void * data, int size)
174 bool dumping_packet = false;
175 if(INTERNET_SIMULATOR)
176 dumping_packet = (rand()%10==0); //easy
177 //dumping_packet = (rand()%4==0); // hard
180 /*dstream<<DPS<<"UDPSocket("<<(int)m_handle
181 <<")::Send(): destination=";*/
183 dstream<<(int)m_handle<<" -> ";
185 dstream<<", size="<<size<<", data=";
186 for(int i=0; i<size && i<20; i++){
187 if(i%2==0) printf(" ");
188 DEBUGPRINT("%.2X", ((int)((const char*)data)[i])&0xff);
193 dstream<<" (DUMPED BY INTERNET_SIMULATOR)";
196 else if(dumping_packet)
198 // Lol let's forget it
199 dstream<<"UDPSocket::Send(): "
200 "INTERNET_SIMULATOR: dumping packet."
208 address.sin_family = AF_INET;
209 address.sin_addr.s_addr = htonl(destination.getAddress());
210 address.sin_port = htons(destination.getPort());
212 int sent = sendto(m_handle, (const char*)data, size,
213 0, (sockaddr*)&address, sizeof(sockaddr_in));
217 throw SendFailedException("Failed to send packet");
221 int UDPSocket::Receive(Address & sender, void * data, int size)
223 if(WaitData(m_timeout_ms) == false)
229 socklen_t address_len = sizeof(address);
231 int received = recvfrom(m_handle, (char*)data,
232 size, 0, (sockaddr*)&address, &address_len);
237 unsigned int address_ip = ntohl(address.sin_addr.s_addr);
238 unsigned int address_port = ntohs(address.sin_port);
240 sender = Address(address_ip, address_port);
243 //dstream<<DPS<<"UDPSocket("<<(int)m_handle<<")::Receive(): sender=";
244 dstream<<DPS<<(int)m_handle<<" <- ";
246 //dstream<<", received="<<received<<std::endl;
247 dstream<<", size="<<received<<", data=";
248 for(int i=0; i<received && i<20; i++){
249 if(i%2==0) printf(" ");
250 DEBUGPRINT("%.2X", ((int)((const char*)data)[i])&0xff);
260 int UDPSocket::GetHandle()
265 void UDPSocket::setTimeoutMs(int timeout_ms)
267 m_timeout_ms = timeout_ms;
270 bool UDPSocket::WaitData(int timeout_ms)
275 // Initialize the set
277 FD_SET(m_handle, &readset);
279 // Initialize time out struct
282 tv.tv_usec = timeout_ms * 1000;
284 result = select(m_handle+1, &readset, NULL, NULL, &tv);
288 /*dstream<<"Select timed out (timeout_ms="
289 <<timeout_ms<<")"<<std::endl;*/
294 dstream<<(int)m_handle<<": Select failed: "<<strerror(errno)<<std::endl;
296 dstream<<(int)m_handle<<": WSAGetLastError()="<<WSAGetLastError()<<std::endl;
298 throw SocketException("Select failed");
300 else if(FD_ISSET(m_handle, &readset) == false){
302 //dstream<<"Select reported no data in m_handle"<<std::endl;
307 //dstream<<"Select reported data in m_handle"<<std::endl;