5 * Created by Victor Grishchenko on 3/9/09.
6 * Copyright 2009 Delft University of Technology. All rights reserved.
13 typedef int socklen_t;
15 #include <arpa/inet.h>
21 tint Datagram::now = Datagram::Time();
22 tint Datagram::epoch = now;
23 uint32_t Address::LOCALHOST = INADDR_LOOPBACK;
24 uint64_t Datagram::dgrams_up=0, Datagram::dgrams_down=0,
25 Datagram::bytes_up=0, Datagram::bytes_down=0;
27 char* Datagram::TimeStr (tint time) {
28 assert(!time || time>=epoch);
29 static char ret_str[4][32]; // wow
36 int hours = time/TINT_HOUR;
38 int mins = time/TINT_MIN;
40 int secs = time/TINT_SEC;
42 int msecs = time/TINT_MSEC;
44 int usecs = time/TINT_uSEC;
45 sprintf(ret_str[i],"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
49 int Datagram::Send () {
50 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
51 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
62 int Datagram::Recv () {
63 socklen_t addrlen = sizeof(struct sockaddr_in);
65 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
66 (struct sockaddr*)&(addr), &addrlen);
69 print_error("error on recv");
78 SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
79 struct timeval timeout;
80 timeout.tv_sec = usec/TINT_SEC;
81 timeout.tv_usec = usec%TINT_SEC;
86 for(int i=0; i<sockcnt; i++) {
87 FD_SET(sockets[i],&bases);
88 FD_SET(sockets[i],&err);
89 if (sockets[i]>max_sock_fd)
90 max_sock_fd = sockets[i];
92 int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
95 for (int i=0; i<=sockcnt; i++)
96 if (FD_ISSET(sockets[i],&bases))
99 print_error("select fails");
101 return INVALID_SOCKET;
104 tint Datagram::Time () {
105 HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
106 tint ret = tod->getTimeUSec();
107 //DLOG(INFO)<<"now is "<<ret;
111 SOCKET Datagram::Bind (Address addr_) {
112 struct sockaddr_in addr = addr_;
114 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
115 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
116 print_error("socket() fails");
117 return INVALID_SOCKET;
121 ioctlsocket(fd, FIONBIO, &enable);
122 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
123 print_error("setsockopt fails");
124 return INVALID_SOCKET;
126 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
127 print_error("setsockopt2 fails");
128 return INVALID_SOCKET;
131 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
132 return INVALID_SOCKET;
133 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
134 print_error("setsockopt fails");
135 return INVALID_SOCKET;
137 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
138 print_error("setsockopt2 fails");
139 return INVALID_SOCKET;
142 dprintf("socket buffers: %i send %i recv\n",sndbuf,rcvbuf);
143 if (::bind(fd, (sockaddr*)&addr, len) != 0) {
144 print_error("bind fails");
145 return INVALID_SOCKET;
150 void Datagram::Close (int sock) { // remove from fd_set
152 if (closesocket(sock)!=0)
154 if (::close(sock)!=0)
156 print_error("on closing a socket");
160 std::string sock2str (struct sockaddr_in addr) {
163 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
165 struct in_addr inaddr;
166 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
167 strncpy(ipch, inet_ntoa(inaddr),32);
169 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
171 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
172 return std::string(ipch);
176 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
177 std::string addrs = sock2str(addr);
178 char hex[MAXDGRAMSZ*2];
179 for(int i=offset; i<length; i++)
180 sprintf(hex+i*2,"%02x",buf[i]);
181 std::string hexs(hex+offset*2,(length-offset)*2);
182 return addrs + '\t' + hexs;