3 * nice IPv4 UDP wrappers
5 * Created by Victor Grishchenko, Arno Bakker on 3/9/09.
6 * Copyright 2009 Delft University of Technology. All rights reserved.
20 #define MAXDGRAMSZ 2800
22 #define INVALID_SOCKET -1
26 /** IPv4 address, just a nice wrapping around struct sockaddr_in. */
28 struct sockaddr_in addr;
29 static uint32_t LOCALHOST;
30 void set_port (uint16_t port) {
31 addr.sin_port = htons(port);
33 void set_port (const char* port_str) {
35 if (sscanf(port_str,"%i",&p))
38 void set_ipv4 (uint32_t ipv4) {
39 addr.sin_addr.s_addr = htonl(ipv4);
41 void set_ipv4 (const char* ipv4_str) ;
42 //{ inet_aton(ipv4_str,&(addr.sin_addr)); }
44 memset(&addr,0,sizeof(struct sockaddr_in));
45 addr.sin_family = AF_INET;
50 Address(const char* ip, uint16_t port) {
55 Address(const char* ip_port);
56 Address(uint16_t port) {
58 set_ipv4((uint32_t)INADDR_ANY);
61 Address(uint32_t ipv4addr, uint16_t port) {
66 Address(const struct sockaddr_in& address) : addr(address) {}
67 uint32_t ipv4 () const { return ntohl(addr.sin_addr.s_addr); }
68 uint16_t port () const { return ntohs(addr.sin_port); }
69 operator sockaddr_in () const {return addr;}
70 bool operator == (const Address& b) const {
71 return addr.sin_family==b.addr.sin_family &&
72 addr.sin_port==b.addr.sin_port &&
73 addr.sin_addr.s_addr==b.addr.sin_addr.s_addr;
75 const char* str () const {
76 static char rs[4][32];
79 sprintf(rs[i],"%i.%i.%i.%i:%i",ipv4()>>24,(ipv4()>>16)&0xff,
80 (ipv4()>>8)&0xff,ipv4()&0xff,port());
83 bool operator != (const Address& b) const { return !(*this==b); }
87 typedef void (*sockcb_t) (SOCKET);
89 sckrwecb_t (SOCKET s=0, sockcb_t mr=NULL, sockcb_t mw=NULL, sockcb_t oe=NULL) :
90 sock(s), may_read(mr), may_write(mw), on_error(oe) {}
98 /** UDP datagram class, a nice wrapping around sendto/recvfrom/select.
99 Reading/writing from/to a datagram is done in a FIFO (deque) fashion:
100 written data is appended to the tail (push) while read data is
101 taken from the "head" of the buffer. */
107 uint8_t buf[MAXDGRAMSZ*2];
109 #define DGRAM_MAX_SOCK_OPEN 128
110 static int sock_count;
111 static sckrwecb_t sock_open[DGRAM_MAX_SOCK_OPEN];
115 /** bind to the address */
116 static SOCKET Bind(Address address, sckrwecb_t callbacks=sckrwecb_t());
118 /** close the port */
119 static void Close(SOCKET sock);
121 /** the current time */
124 /** wait till one of the sockets has some io to do; usec is the timeout */
125 static SOCKET Wait (tint usec);
127 static bool Listen3rdPartySocket (sckrwecb_t cb) ;
129 static void Shutdown ();
131 static SOCKET default_socket()
132 { return sock_count ? sock_open[0].sock : INVALID_SOCKET; }
134 static tint now, epoch, start;
135 static uint64_t dgrams_up, dgrams_down, bytes_up, bytes_down;
137 /** This constructor is normally used to SEND something to the address. */
138 Datagram (SOCKET socket, const Address addr_) : addr(addr_), offset(0),
139 length(0), sock(socket) {}
140 /** This constructor is normally used to RECEIVE something at the socket. */
141 Datagram (SOCKET socket) : offset(0), length(0), sock(socket) {
144 /** space remaining */
145 int space () const { return MAXDGRAMSZ-length; }
146 /** size of the data (not counting UDP etc headers) */
147 int size() const { return length-offset; }
148 std::string str() const { return std::string((char*)buf+offset,size()); }
149 const uint8_t* operator * () const { return buf+offset; }
150 const Address& address () const { return addr; }
151 /** Append some data at the back */
152 int Push (const uint8_t* data, int l) { // scatter-gather one day
153 int toc = l<space() ? l : space();
154 memcpy(buf+length,data,toc);
158 /** Read something from the front of the datagram */
159 int Pull (uint8_t** data, int l) {
160 int toc = l<size() ? l : size();
161 //memcpy(data,buf+offset,toc);
170 void Clear() { offset=length=0; }
172 void PushString (std::string str) {
173 Push((uint8_t*)str.c_str(),str.size());
175 void Push8 (uint8_t b) {
178 void Push16 (uint16_t w) {
179 *(uint16_t*)(buf+length) = htons(w);
182 void Push32 (uint32_t i) {
183 *(uint32_t*)(buf+length) = htonl(i);
186 void Push64 (uint64_t l) {
187 *(uint32_t*)(buf+length) = htonl((uint32_t)(l>>32));
188 *(uint32_t*)(buf+length+4) = htonl((uint32_t)(l&0xffffffff));
191 void PushHash (const Sha1Hash& hash) {
192 Push((uint8_t*)hash.bits, Sha1Hash::SIZE);
196 if (size()<1) return 0;
197 return buf[offset++];
200 if (size()<2) return 0;
202 return ntohs(*(uint16_t*)(buf+offset-2));
205 if (size()<4) return 0;
206 uint32_t i = ntohl(*(uint32_t*)(buf+offset));
211 if (size()<8) return 0;
212 uint64_t l = ntohl(*(uint32_t*)(buf+offset));
214 l |= ntohl(*(uint32_t*)(buf+offset+4));
218 Sha1Hash PullHash() {
219 if (size()<Sha1Hash::SIZE) return Sha1Hash::ZERO;
220 offset += Sha1Hash::SIZE;
221 return Sha1Hash(false,(char*)buf+offset-Sha1Hash::SIZE);
223 //std::string to_string () const ;
227 const char* tintstr(tint t=0);
228 std::string sock2str (struct sockaddr_in addr);