5 * Created by Victor Grishchenko, Arno Bakker on 3/9/09.
6 * Copyright 2009 Delft University of Technology. All rights reserved.
13 typedef int socklen_t;
15 #include <arpa/inet.h>
24 tint Datagram::now = Datagram::Time();
25 tint Datagram::start = now;
26 tint Datagram::epoch = now/360000000LL*360000000LL; // make logs mergeable
27 uint32_t Address::LOCALHOST = INADDR_LOOPBACK;
28 uint64_t Datagram::dgrams_up=0, Datagram::dgrams_down=0,
29 Datagram::bytes_up=0, Datagram::bytes_down=0;
30 sckrwecb_t Datagram::sock_open[] = {};
31 int Datagram::sock_count = 0;
33 const char* tintstr (tint time) {
36 static char ret_str[4][32]; // wow
41 time -= Datagram::epoch;
43 int hours = time/TINT_HOUR;
45 int mins = time/TINT_MIN;
47 int secs = time/TINT_SEC;
49 int msecs = time/TINT_MSEC;
51 int usecs = time/TINT_uSEC;
52 sprintf(ret_str[i],"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
56 void Address::set_ipv4 (const char* ip_str) {
57 struct hostent *h = gethostbyname(ip_str);
59 print_error("cannot lookup address");
62 addr.sin_addr.s_addr = *(u_long *) h->h_addr_list[0];
67 Address::Address(const char* ip_port) {
69 if (strlen(ip_port)>=1024)
72 strncpy(ipp,ip_port,1024);
73 char* semi = strchr(ipp,':');
79 if (strchr(ipp, '.')) {
81 set_port((uint16_t)0);
83 set_ipv4(INADDR_LOOPBACK);
90 bool Datagram::Listen3rdPartySocket (sckrwecb_t cb) {
92 while (i<sock_count && sock_open[i].sock!=cb.sock) i++;
94 if (i==DGRAM_MAX_SOCK_OPEN)
99 //if (!cb.may_read && !cb.may_write && !cb.on_error)
100 // sock_open[i] = sock_open[--sock_count];
105 void Datagram::Shutdown () {
107 Close(sock_open[sock_count].sock);
111 int Datagram::Send () {
112 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
113 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
115 perror("can't send");
124 int Datagram::Recv () {
125 socklen_t addrlen = sizeof(struct sockaddr_in);
127 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ*2, 0,
128 (struct sockaddr*)&(addr.addr), &addrlen);
131 print_error("error on recv");
140 SOCKET Datagram::Wait (tint usec) {
141 struct timeval timeout;
142 timeout.tv_sec = usec/TINT_SEC;
143 timeout.tv_usec = usec%TINT_SEC;
145 fd_set rdfd, wrfd, errfd;
149 for(int i=0; i<sock_count; i++) {
150 if (sock_open[i].may_read!=0)
151 FD_SET(sock_open[i].sock,&rdfd);
152 if (sock_open[i].may_write!=0)
153 FD_SET(sock_open[i].sock,&wrfd);
154 if (sock_open[i].on_error!=0)
155 FD_SET(sock_open[i].sock,&errfd);
156 if (sock_open[i].sock>max_sock_fd)
157 max_sock_fd = sock_open[i].sock;
159 SOCKET sel = select(max_sock_fd+1, &rdfd, &wrfd, &errfd, &timeout);
162 for (int i=0; i<=sock_count; i++) {
163 sckrwecb_t& sct = sock_open[i];
164 if (sct.may_read && FD_ISSET(sct.sock,&rdfd))
165 (*(sct.may_read))(sct.sock);
166 if (sct.may_write && FD_ISSET(sct.sock,&wrfd))
167 (*(sct.may_write))(sct.sock);
168 if (sct.on_error && FD_ISSET(sct.sock,&errfd))
169 (*(sct.on_error))(sct.sock);
172 print_error("select fails");
177 tint Datagram::Time () {
178 //HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
179 //tint ret = tod->getTimeUSec();
180 //DLOG(INFO)<<"now is "<<ret;
181 return now = usec_time();
184 SOCKET Datagram::Bind (Address address, sckrwecb_t callbacks) {
185 struct sockaddr_in addr = address;
187 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
188 #define dbnd_ensure(x) { if (!(x)) { \
189 print_error("binding fails"); close_socket(fd); return INVALID_SOCKET; } }
190 dbnd_ensure ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0 );
191 dbnd_ensure( make_socket_nonblocking(fd) ); // FIXME may remove this
193 dbnd_ensure ( setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
194 (setsockoptptr_t)&sndbuf, sizeof(int)) == 0 );
195 dbnd_ensure ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
196 (setsockoptptr_t)&rcvbuf, sizeof(int)) == 0 );
197 //setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (setsockoptptr_t)&enable, sizeof(int));
198 dbnd_ensure ( ::bind(fd, (sockaddr*)&addr, len) == 0 );
200 Datagram::sock_open[Datagram::sock_count++] = callbacks;
204 void Datagram::Close (SOCKET sock) {
205 for(int i=0; i<Datagram::sock_count; i++)
206 if (Datagram::sock_open[i].sock==sock)
207 Datagram::sock_open[i] = Datagram::sock_open[--Datagram::sock_count];
208 if (!close_socket(sock))
209 print_error("on closing a socket");
213 std::string sock2str (struct sockaddr_in addr) {
216 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
218 struct in_addr inaddr;
219 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
220 strncpy(ipch, inet_ntoa(inaddr),32);
222 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
224 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
225 return std::string(ipch);
229 std::string Datagram::to_string () const { // TODO: pretty-print swift
230 std::string addrs = sock2str(addr);
231 char hex[MAXDGRAMSZ*2];
232 for(int i=offset; i<length; i++)
233 sprintf(hex+i*2,"%02x",buf[i]);
234 std::string hexs(hex+offset*2,(length-offset)*2);
235 return addrs + '\t' + hexs;