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>
17 #include <glog/logging.h>
22 tint Datagram::now = Datagram::Time();
23 tint Datagram::epoch = now;
24 uint32_t Datagram::Address::LOCALHOST = INADDR_LOOPBACK;
25 uint64_t Datagram::dgrams_up=0, Datagram::dgrams_down=0,
26 Datagram::bytes_up=0, Datagram::bytes_down=0;
28 char* Datagram::TimeStr (tint time) {
29 assert(!time || time>=epoch);
30 static char ret_str[4][32]; // wow
37 int hours = time/TINT_HOUR;
39 int mins = time/TINT_MIN;
41 int secs = time/TINT_SEC;
43 int msecs = time/TINT_MSEC;
45 int usecs = time/TINT_uSEC;
46 sprintf(ret_str[i],"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
50 int Datagram::Send () {
51 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
52 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
63 int Datagram::Recv () {
64 socklen_t addrlen = sizeof(struct sockaddr_in);
66 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
67 (struct sockaddr*)&(addr), &addrlen);
68 if (length<0) // FIXME FIXME FIXME
70 PLOG(ERROR)<<"on recv" << WSAGetLastError() << "\n";
72 PLOG(ERROR)<<"on recv";
81 SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
82 struct timeval timeout;
83 timeout.tv_sec = usec/TINT_SEC;
84 timeout.tv_usec = usec%TINT_SEC;
89 for(int i=0; i<sockcnt; i++) {
90 FD_SET(sockets[i],&bases);
91 FD_SET(sockets[i],&err);
92 if (sockets[i]>max_sock_fd)
93 max_sock_fd = sockets[i];
95 int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
98 for (int i=0; i<=sockcnt; i++)
99 if (FD_ISSET(sockets[i],&bases))
103 PLOG(ERROR)<<"select fails" << WSAGetLastError() << "\n";
105 PLOG(ERROR)<<"select fails";
111 tint Datagram::Time () {
112 HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
113 tint ret = tod->getTimeUSec();
114 //DLOG(INFO)<<"now is "<<ret;
118 SOCKET Datagram::Bind (Address addr_) {
119 struct sockaddr_in addr = addr_;
121 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
122 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
123 PLOG(ERROR)<<"socket fails";
128 ioctlsocket(fd, FIONBIO, &enable);
129 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
130 PLOG(ERROR)<<"setsockopt fails";
133 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
134 PLOG(ERROR)<<"setsockopt2 fails";
138 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
140 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
141 PLOG(ERROR)<<"setsockopt fails";
144 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
145 PLOG(ERROR)<<"setsockopt2 fails";
149 printf("BUFS: %i %i\n",sndbuf,rcvbuf);
150 /*memset(&addr, 0, sizeof(struct sockaddr_in));
151 addr.sin_family = AF_INET;
152 addr.sin_port = htons(portno);
153 addr.sin_addr.s_addr = INADDR_ANY;*/
154 if (::bind(fd, (sockaddr*)&addr, len) != 0) {
155 PLOG(ERROR)<<"bind fails";
161 void Datagram::Close (int sock) { // remove from fd_set
163 if (closesocket(sock)!=0)
165 if (::close(sock)!=0)
167 PLOG(ERROR)<<"on closing a socket";
171 std::string sock2str (struct sockaddr_in addr) {
174 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
176 struct in_addr inaddr;
177 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
178 strncpy(ipch, inet_ntoa(inaddr),32);
180 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
182 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
183 return std::string(ipch);
187 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
188 std::string addrs = sock2str(addr);
189 char hex[MAXDGRAMSZ*2];
190 for(int i=offset; i<length; i++)
191 sprintf(hex+i*2,"%02x",buf[i]);
192 std::string hexs(hex+offset*2,(length-offset)*2);
193 return addrs + '\t' + hexs;