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>
18 #include <glog/logging.h>
23 tint Datagram::now = Datagram::Time();
24 tint Datagram::epoch = now;
25 uint32_t Datagram::Address::LOCALHOST = INADDR_LOOPBACK;
27 char* Datagram::TimeStr (tint time) {
28 static char ret_str[128];
32 int hours = time/TINT_HOUR;
34 int mins = time/TINT_MIN;
36 int secs = time/TINT_SEC;
38 int msecs = time/TINT_MSEC;
40 int usecs = time/TINT_uSEC;
41 sprintf(ret_str,"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
45 int Datagram::Send () {
47 if (rand()%RND_DROP==0) {
49 dprintf("%s datagram killed\n",TimeStr());
53 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
54 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
61 int Datagram::Recv () {
62 socklen_t addrlen = sizeof(struct sockaddr_in);
64 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
65 (struct sockaddr*)&(addr), &addrlen);
66 if (length<0) // FIXME FIXME FIXME
68 PLOG(ERROR)<<"on recv" << WSAGetLastError() << "\n";
70 PLOG(ERROR)<<"on recv";
77 SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
78 dprintf("waiting (%i socks)\n",sockcnt);
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))
100 PLOG(ERROR)<<"select fails" << WSAGetLastError() << "\n";
102 PLOG(ERROR)<<"select fails";
108 tint Datagram::Time () {
109 HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
110 tint ret = tod->getTimeUSec();
111 //DLOG(INFO)<<"now is "<<ret;
115 SOCKET Datagram::Bind (Address addr_) {
116 struct sockaddr_in addr = addr_;
118 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
119 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
120 PLOG(ERROR)<<"socket fails";
125 ioctlsocket(fd, FIONBIO, &enable);
126 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
127 PLOG(ERROR)<<"setsockopt fails";
130 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
131 PLOG(ERROR)<<"setsockopt2 fails";
135 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
137 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
138 PLOG(ERROR)<<"setsockopt fails";
141 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
142 PLOG(ERROR)<<"setsockopt2 fails";
146 printf("BUFS: %i %i\n",sndbuf,rcvbuf);
147 /*memset(&addr, 0, sizeof(struct sockaddr_in));
148 addr.sin_family = AF_INET;
149 addr.sin_port = htons(portno);
150 addr.sin_addr.s_addr = INADDR_ANY;*/
151 if (::bind(fd, (sockaddr*)&addr, len) != 0) {
152 PLOG(ERROR)<<"bind fails";
158 void Datagram::Close (int sock) { // remove from fd_set
160 if (closesocket(sock)!=0)
162 if (::close(sock)!=0)
164 PLOG(ERROR)<<"on closing a socket";
168 std::string sock2str (struct sockaddr_in addr) {
171 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
173 struct in_addr inaddr;
174 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
175 strncpy(ipch, inet_ntoa(inaddr),32);
177 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
179 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
180 return std::string(ipch);
184 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
185 std::string addrs = sock2str(addr);
186 char hex[MAXDGRAMSZ*2];
187 for(int i=offset; i<length; i++)
188 sprintf(hex+i*2,"%02x",buf[i]);
189 std::string hexs(hex+offset*2,(length-offset)*2);
190 return addrs + '\t' + hexs;