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;
31 const char* tintstr (tint time) {
34 static char ret_str[4][32]; // wow
39 time -= Datagram::epoch;
41 int hours = time/TINT_HOUR;
43 int mins = time/TINT_MIN;
45 int secs = time/TINT_SEC;
47 int msecs = time/TINT_MSEC;
49 int usecs = time/TINT_uSEC;
50 sprintf(ret_str[i],"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
54 void Address::set_ipv4 (const char* ip_str) {
55 struct hostent *h = gethostbyname(ip_str);
57 print_error("cannot lookup address");
60 addr.sin_addr.s_addr = *(u_long *) h->h_addr_list[0];
65 Address::Address(const char* ip_port) {
67 if (strlen(ip_port)>=1024)
70 strncpy(ipp,ip_port,1024);
71 char* semi = strchr(ipp,':');
77 if (strchr(ipp, '.')) {
79 set_port((uint16_t)0);
81 set_ipv4(INADDR_LOOPBACK);
88 int Datagram::Send () {
89 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
90 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
101 int Datagram::Recv () {
102 socklen_t addrlen = sizeof(struct sockaddr_in);
104 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
105 (struct sockaddr*)&(addr.addr), &addrlen);
108 print_error("error on recv");
117 SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
118 struct timeval timeout;
119 timeout.tv_sec = usec/TINT_SEC;
120 timeout.tv_usec = usec%TINT_SEC;
125 for(int i=0; i<sockcnt; i++) {
126 FD_SET(sockets[i],&bases);
127 FD_SET(sockets[i],&err);
128 if (sockets[i]>max_sock_fd)
129 max_sock_fd = sockets[i];
131 int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
134 for (int i=0; i<=sockcnt; i++)
135 if (FD_ISSET(sockets[i],&bases))
138 print_error("select fails");
140 return INVALID_SOCKET;
143 tint Datagram::Time () {
144 //HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
145 //tint ret = tod->getTimeUSec();
146 //DLOG(INFO)<<"now is "<<ret;
147 return now = usec_time();
150 SOCKET Datagram::Bind (Address addr_) {
151 struct sockaddr_in addr = addr_;
153 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
154 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
155 print_error("socket() fails");
156 return INVALID_SOCKET;
160 ioctlsocket(fd, FIONBIO, &enable);
161 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
162 print_error("setsockopt fails");
163 return INVALID_SOCKET;
165 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
166 print_error("setsockopt2 fails");
167 return INVALID_SOCKET;
169 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable, sizeof(int));
172 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
173 return INVALID_SOCKET;
174 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
175 print_error("setsockopt fails");
176 return INVALID_SOCKET;
178 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
179 print_error("setsockopt2 fails");
180 return INVALID_SOCKET;
182 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
184 dprintf("socket buffers: %i send %i recv\n",sndbuf,rcvbuf);
185 if (::bind(fd, (sockaddr*)&addr, len) != 0) {
186 print_error("bind fails");
187 return INVALID_SOCKET;
192 void Datagram::Close (int sock) { // remove from fd_set
194 if (closesocket(sock)!=0)
196 if (::close(sock)!=0)
198 print_error("on closing a socket");
202 std::string sock2str (struct sockaddr_in addr) {
205 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
207 struct in_addr inaddr;
208 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
209 strncpy(ipch, inet_ntoa(inaddr),32);
211 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
213 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
214 return std::string(ipch);
218 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
219 std::string addrs = sock2str(addr);
220 char hex[MAXDGRAMSZ*2];
221 for(int i=offset; i<length; i++)
222 sprintf(hex+i*2,"%02x",buf[i]);
223 std::string hexs(hex+offset*2,(length-offset)*2);
224 return addrs + '\t' + hexs;