import
[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 Technical University. All rights reserved.
7  *
8  */
9 #include <arpa/inet.h>
10 #include <glog/logging.h>
11 #include "datagram.h"
12
13 namespace p2tp {
14
15 tint Datagram::now = Datagram::Time();
16
17 int Datagram::Send () {
18         int r = sendto(sock,buf+offset,length-offset,0,
19                                    (struct sockaddr*)&(addr),sizeof(struct sockaddr_in));
20         offset=0;
21         length=0;
22         now = Time();
23         return r;
24 }
25
26 int Datagram::Recv () {
27         socklen_t addrlen = sizeof(struct sockaddr_in);
28         offset = 0;
29         length = recvfrom (sock, buf, MAXDGRAMSZ, 0, 
30                                            (struct sockaddr*)&(addr), &addrlen);
31         if (length<0)
32                 PLOG(ERROR)<<"on recv";
33         now = Time();
34         return length;
35 }
36
37
38 int Datagram::Wait (int sockcnt, int* sockets, tint usec) {
39         LOG(INFO)<<"waiting for "<<sockcnt;
40         struct timeval timeout;
41         timeout.tv_sec = usec/SEC;
42         timeout.tv_usec = usec%SEC;
43         int max_sock_fd = 0;
44         fd_set bases, err;
45         FD_ZERO(&bases);
46         FD_ZERO(&err);
47         for(int i=0; i<sockcnt; i++) {
48                 FD_SET(sockets[i],&bases);
49                 FD_SET(sockets[i],&err);
50                 if (sockets[i]>max_sock_fd)
51                         max_sock_fd = sockets[i];
52         }
53         int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
54         if (sel>0) {
55                 for (int i=0; i<=sockcnt; i++)
56                         if (FD_ISSET(sockets[i],&bases))
57                                 return sockets[i];
58         } else if (sel<0) 
59                 PLOG(ERROR)<<"select fails";
60         return -1;
61 }
62
63 tint Datagram::Time () {
64         struct timeval t;
65         gettimeofday(&t,NULL);
66         tint ret;
67         ret = t.tv_sec;
68         ret *= 1000000;
69         ret += t.tv_usec;
70         //DLOG(INFO)<<"now is "<<ret;
71         return now=ret;
72 }
73
74 int Datagram::Bind (int portno) {
75     struct sockaddr_in addr;
76         int fd, len = sizeof(struct sockaddr_in), 
77         sndbuf=1<<20, rcvbuf=1<<20;
78         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
79                 PLOG(ERROR)<<"socket fails";
80         return -1;
81     }
82         if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
83                 return -2;
84         if ( setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
85         PLOG(ERROR)<<"setsockopt fails";
86         return -3;
87     }
88         if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
89         PLOG(ERROR)<<"setsockopt2 fails";
90         return -3;
91     }
92     printf("BUFS: %i %i\n",sndbuf,rcvbuf);
93     memset(&addr, 0, sizeof(struct sockaddr_in));
94         addr.sin_family = AF_INET;
95     addr.sin_port = htons(portno);
96     addr.sin_addr.s_addr = INADDR_ANY;
97         if (::bind(fd, (struct sockaddr*)&addr, len) != 0) {
98         PLOG(ERROR)<<"bind fails";
99         return -4;
100     }
101         return fd;
102 }
103
104 void Datagram::Close (int sock) { // remove from fd_set
105         if (::close(sock)!=0)
106                 PLOG(ERROR)<<"on closing a socket";
107 }
108
109
110 std::string sock2str (struct sockaddr_in addr) {
111         char ipch[32];
112         inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
113         sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
114         return std::string(ipch);
115 }
116
117
118 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
119         std::string addrs = sock2str(addr);
120         char hex[MAXDGRAMSZ*2];
121         for(int i=offset; i<length; i++) 
122                 sprintf(hex+i*2,"%02x",buf[i]);
123         std::string hexs(hex+offset*2,(length-offset)*2);
124         return addrs + '\t' + hexs;
125 }
126
127 }