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 uint32_t Datagram::Address::LOCALHOST = INADDR_LOOPBACK;
25 int Datagram::Send () {
26 int r = sendto(sock,(const char *)buf+offset,length-offset,0,
27 (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
34 int Datagram::Recv () {
35 socklen_t addrlen = sizeof(struct sockaddr_in);
37 length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
38 (struct sockaddr*)&(addr), &addrlen);
41 PLOG(ERROR)<<"on recv" << WSAGetLastError() << "\n";
43 PLOG(ERROR)<<"on recv";
50 SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
51 // ARNOTODO: LOG commented out, it causes a crash on win32 (in a strlen()
52 // done as part of a std::local::name() ??
54 //LOG(INFO)<<"waiting for "<<sockcnt;
55 struct timeval timeout;
56 timeout.tv_sec = usec/TINT_SEC;
57 timeout.tv_usec = usec%TINT_SEC;
62 for(int i=0; i<sockcnt; i++) {
63 FD_SET(sockets[i],&bases);
64 FD_SET(sockets[i],&err);
65 if (sockets[i]>max_sock_fd)
66 max_sock_fd = sockets[i];
68 int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
70 for (int i=0; i<=sockcnt; i++)
71 if (FD_ISSET(sockets[i],&bases))
75 PLOG(ERROR)<<"select fails" << WSAGetLastError() << "\n";
77 PLOG(ERROR)<<"select fails";
80 // Arno: may return 0 when timeout expired
84 tint Datagram::Time () {
85 HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
86 tint ret = tod->getTimeUSec();
87 //DLOG(INFO)<<"now is "<<ret;
91 SOCKET Datagram::Bind (Address addr_) {
92 struct sockaddr_in addr = addr_;
94 int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
95 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
96 PLOG(ERROR)<<"socket fails";
101 ioctlsocket(fd, FIONBIO, &enable);
102 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
103 PLOG(ERROR)<<"setsockopt fails";
106 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
107 PLOG(ERROR)<<"setsockopt2 fails";
111 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
113 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
114 PLOG(ERROR)<<"setsockopt fails";
117 if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
118 PLOG(ERROR)<<"setsockopt2 fails";
122 printf("BUFS: %i %i\n",sndbuf,rcvbuf);
123 /*memset(&addr, 0, sizeof(struct sockaddr_in));
124 addr.sin_family = AF_INET;
125 addr.sin_port = htons(portno);
126 addr.sin_addr.s_addr = INADDR_ANY;*/
127 if (::bind(fd, (sockaddr*)&addr, len) != 0) {
128 PLOG(ERROR)<<"bind fails";
134 void Datagram::Close (int sock) { // remove from fd_set
136 if (closesocket(sock)!=0)
138 if (::close(sock)!=0)
140 PLOG(ERROR)<<"on closing a socket";
144 std::string sock2str (struct sockaddr_in addr) {
147 //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
149 struct in_addr inaddr;
150 memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
151 strncpy(ipch, inet_ntoa(inaddr),32);
153 inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
155 sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
156 return std::string(ipch);
160 std::string Datagram::to_string () const { // TODO: pretty-print P2TP
161 std::string addrs = sock2str(addr);
162 char hex[MAXDGRAMSZ*2];
163 for(int i=offset; i<length; i++)
164 sprintf(hex+i*2,"%02x",buf[i]);
165 std::string hexs(hex+offset*2,(length-offset)*2);
166 return addrs + '\t' + hexs;