cong ctrl in progress
[swift-upb.git] / datagram.cpp
1 /*
2  *  datagram.cpp
3  *  serp++
4  *
5  *  Created by Victor Grishchenko on 3/9/09.
6  *  Copyright 2009 Delft University of Technology. All rights reserved.
7  *
8  */
9 #include <iostream>
10
11 #ifdef _WIN32
12     #include <winsock2.h>
13     typedef int socklen_t;
14 #else
15     #include <arpa/inet.h>
16 #endif
17 #include <glog/logging.h>
18 #include "datagram.h"
19
20 namespace p2tp {
21
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;
27
28 char* Datagram::TimeStr (tint time) {
29     assert(!time || time>=epoch);
30     static char ret_str[4][32]; // wow
31     static int i;
32     i = (i+1) & 3;
33     if (time==0)
34         time = now;
35     time -= epoch;
36     assert(time>=0);
37     int hours = time/TINT_HOUR;
38     time %= TINT_HOUR;
39     int mins = time/TINT_MIN;
40     time %= TINT_MIN;
41     int secs = time/TINT_SEC;
42     time %= TINT_SEC;
43     int msecs = time/TINT_MSEC;
44     time %= TINT_MSEC;
45     int usecs = time/TINT_uSEC;
46     sprintf(ret_str[i],"%i_%02i_%02i_%03i_%03i",hours,mins,secs,msecs,usecs);
47     return ret_str[i];
48 }
49     
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));
53     if (r<0)
54         perror("can't send");
55         //offset=0;
56         //length=0;
57     dgrams_up++;
58     bytes_up+=size();
59         Time();
60         return r;
61 }
62
63 int Datagram::Recv () {
64         socklen_t addrlen = sizeof(struct sockaddr_in);
65         offset = 0;
66         length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
67                                            (struct sockaddr*)&(addr), &addrlen);
68         if (length<0) // FIXME FIXME FIXME 
69 #ifdef _WIN32
70                 PLOG(ERROR)<<"on recv" << WSAGetLastError() << "\n";
71 #else
72                 PLOG(ERROR)<<"on recv";
73 #endif
74     dgrams_down++;
75     bytes_down+=length;
76         Time();
77         return length;
78 }
79
80
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;
85         int max_sock_fd = 0;
86         fd_set bases, err;
87         FD_ZERO(&bases);
88         FD_ZERO(&err);
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];
94         }
95         int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
96     Time();
97         if (sel>0) {
98                 for (int i=0; i<=sockcnt; i++)
99                         if (FD_ISSET(sockets[i],&bases))
100                                 return sockets[i];
101         } else if (sel<0) {
102 #ifdef _WIN32
103                 PLOG(ERROR)<<"select fails" << WSAGetLastError() << "\n";
104 #else
105                 PLOG(ERROR)<<"select fails";
106 #endif
107     } 
108     return -1;
109 }
110
111 tint Datagram::Time () {
112         HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
113         tint ret = tod->getTimeUSec();
114         //DLOG(INFO)<<"now is "<<ret;
115         return now=ret;
116 }
117
118 SOCKET Datagram::Bind (Address addr_) {
119     struct sockaddr_in addr = addr_;
120         SOCKET fd;
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";
124         return -1;
125     }
126 #ifdef _WIN32
127         u_long enable = 1;
128         ioctlsocket(fd, FIONBIO, &enable);
129         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
130         PLOG(ERROR)<<"setsockopt fails";
131         return -3;
132     }
133         if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
134         PLOG(ERROR)<<"setsockopt2 fails";
135         return -3;
136     }
137 #else
138         if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
139                 return -2;
140         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
141         PLOG(ERROR)<<"setsockopt fails";
142         return -3;
143     }
144         if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
145         PLOG(ERROR)<<"setsockopt2 fails";
146         return -3;
147     }
148 #endif
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";
156         return -4;
157     }
158         return fd;
159 }
160
161 void Datagram::Close (int sock) { // remove from fd_set
162 #ifdef _WIN32
163         if (closesocket(sock)!=0)
164 #else
165         if (::close(sock)!=0)
166 #endif
167                 PLOG(ERROR)<<"on closing a socket";
168 }
169
170
171 std::string sock2str (struct sockaddr_in addr) {
172         char ipch[32];
173 #ifdef _WIN32
174         //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
175         // IPv4 only:
176         struct in_addr inaddr;
177         memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
178         strncpy(ipch, inet_ntoa(inaddr),32);
179 #else
180         inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
181 #endif
182         sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
183         return std::string(ipch);
184 }
185
186 /*
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;
194 }*/
195
196 }