001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
Min/Max






















Min/Max






















































Min/Max



























































































































































































































/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <extensions/net/util.hpp>

// check out /Code/omni/references/future/omni/net.hpp

// TODO: add a omni::net::bluetooth socket and have it non-portable code .. example code:
/*
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>

    int main(int argc, char **argv)
    {
        struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
        char buf[1024] = { 0 };
        int s, client, bytes_read;
        socklen_t opt = sizeof(rem_addr);

        if( argc < 2 )
        {    
        printf("usage: %s <bt-port> \n", argv[0]);
        return 1;
        }

        // allocate socket
        s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

        // bind socket to port of the first available
        // local bluetooth adapter
        loc_addr.rc_family = AF_BLUETOOTH;
        loc_addr.rc_bdaddr = *BDADDR_ANY;
        loc_addr.rc_channel = (uint8_t) atoi(argv[1]);
        bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

        // put socket into listening mode
        listen(s, 1);

        // accept one connection
        client = accept(s, (struct sockaddr *)&rem_addr, &opt);

        ba2str( &rem_addr.rc_bdaddr, buf );
        fprintf(stderr, "accepted connection from %s\n", buf);
        memset(buf, 0, sizeof(buf));

        // read data from the client
        bytes_read = read(client, buf, sizeof(buf));
        if( bytes_read > 0 ) {
            printf("received [%s]\n", buf);
        }

        // close connection
        close(client);
        close(s);
        return 0;
    }
*/

// TODO: omni::net::pingreply ping(const std::string& ip);

/*

    //A simple Ping program to ping any address such as google.com in Linux
    //run program as : gcc -o ping ping.c
    // then : ./ping google.com
    //can ping localhost addresses
    //see the RAW socket implementation

    #include <stdio.h>
    #include <signal.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <netdb.h>
    #include <setjmp.h>
    #include <errno.h>
    #define PACKET_SIZE     4096
    #define MAX_WAIT_TIME 5
    #define MAX_NO_PACKETS 3

    char sendpacket[PACKET_SIZE];
    char recvpacket[PACKET_SIZE];
    int sockfd, datalen = 56;
    int nsend = 0, nreceived = 0;
    struct sockaddr_in dest_addr;
    pid_t pid;
    struct sockaddr_in from;
    struct timeval tvrecv;
    void statistics(int signo);
    unsigned short cal_chksum(unsigned short *addr, int len);
    int pack(int pack_no);
    void send_packet(void);
    void recv_packet(void);
    int unpack(char *buf, int len);
    void tv_sub(struct timeval *out, struct timeval *in);

    void statistics(int signo)
    {
        printf("\n--------------------PING statistics-------------------\n");
        printf("%d packets transmitted, %d received , %%%d lost\n", nsend, nreceived, (nsend - nreceived) / nsend * 100);
        close(sockfd);
        exit(1);
    }

    unsigned short cal_chksum(unsigned short *addr, int len)
    {
        int nleft = len;
        int sum = 0;
        unsigned short *w = addr;
        unsigned short answer = 0;

        while (nleft > 1)
        {
            sum += *w++;
            nleft -= 2;
        }

        if (nleft == 1)
        {
            *(unsigned char*)(&answer) = *(unsigned char*)w;
            sum += answer;
        }
        sum = (sum >> 16) + (sum &0xffff);
        sum += (sum >> 16);
        answer = ~sum;
        return answer;
    }

    int pack(int pack_no)
    {
        int i, packsize;
        struct icmp *icmp;
        struct timeval *tval;
        icmp = (struct icmp*)sendpacket;
        icmp->icmp_type = ICMP_ECHO;
        icmp->icmp_code = 0;
        icmp->icmp_cksum = 0;
        icmp->icmp_seq = pack_no;
        icmp->icmp_id = pid;
        packsize = 8+datalen;
        tval = (struct timeval*)icmp->icmp_data;
        gettimeofday(tval, NULL);
        icmp->icmp_cksum = cal_chksum((unsigned short*)icmp, packsize);
        return packsize;
    }

    void send_packet()
    {
        int packetsize;
        while (nsend < MAX_NO_PACKETS)
        {
            nsend++;
            packetsize = pack(nsend);
            if (sendto(sockfd, sendpacket, packetsize, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0)
            {
                perror("sendto error");
                continue;
            } sleep(1);
        }
    }

    void recv_packet()
    {
        int n, fromlen;
        extern int errno;
        signal(SIGALRM, statistics);
        fromlen = sizeof(from);
        while (nreceived < nsend)
        {
            alarm(MAX_WAIT_TIME);
            if ((n = recvfrom(sockfd, recvpacket, sizeof(recvpacket), 0, (struct sockaddr*) &from, &fromlen)) < 0)
            {
                if (errno == EINTR)
                    continue;
                perror("recvfrom error");
                continue;
            } gettimeofday(&tvrecv, NULL);

            if (unpack(recvpacket, n) == - 1)
                continue;

            nreceived++;
        }
    }

    int unpack(char *buf, int len)
    {
        int i, iphdrlen;
        struct ip *ip;
        struct icmp *icmp;
        struct timeval *tvsend;
        double rtt;
        ip = (struct ip*)buf;
        iphdrlen = ip->ip_hl << 2;
        icmp = (struct icmp*)(buf + iphdrlen);
        len -= iphdrlen;
        if (len < 8)
        {
            printf("ICMP packets\'s length is less than 8\n");
            return - 1;
        }

        if ((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == pid))
        {
            tvsend = (struct timeval*)icmp->icmp_data;
            tv_sub(&tvrecv, tvsend);
            rtt = tvrecv.tv_sec * 1000+tvrecv.tv_usec / 1000;
            printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n", len, inet_ntoa(from.sin_addr), icmp->icmp_seq, ip->ip_ttl, rtt);
        }
        else
            return - 1;
    }

    main(int argc, char *argv[])
    {
        struct hostent *host;
        struct protoent *protocol;
        unsigned long inaddr = 0l;
        int waittime = MAX_WAIT_TIME;
        int size = 50 * 1024;
        if (argc < 2)
        {
            printf("usage:%s hostname/IP address\n", argv[0]);
            exit(1);
        }
        
        if ((protocol = getprotobyname("icmp")) == NULL)
        {
            perror("getprotobyname");
            exit(1);
        }

        if ((sockfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0)
        {
            perror("socket error");
            exit(1);
        }

        setuid(getuid());
        setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        bzero(&dest_addr, sizeof(dest_addr));
        dest_addr.sin_family = AF_INET;

        if (inaddr = inet_addr(argv[1]) == INADDR_NONE)
        {
            if ((host = gethostbyname(argv[1])) == NULL)
            {
                perror("gethostbyname error");
                exit(1);
            }
            memcpy((char*) &dest_addr.sin_addr, host->h_addr, host->h_length);
        }
        else
            dest_addr.sin_addr.s_addr = inet_addr(argv[1]);

        pid = getpid();
        printf("PING %s(%s): %d bytes data in ICMP packets.\n", argv[1], inet_ntoa(dest_addr.sin_addr), datalen);
        send_packet();
        recv_packet();
        statistics(SIGALRM);
        return 0;
    }

    void tv_sub(struct timeval *out, struct timeval *in)
    {
        if ((out->tv_usec -= in->tv_usec) < 0)
        {
            --out->tv_sec;
            out->tv_usec += 1000000;
        } out->tv_sec -= in->tv_sec;
    }
*/


// TODO: omni::net::socket_error poll(omni::net::socket_t handle, uint32_t us, omni::net::select_mode mode);