51bfe0eea024a64689bc645f70767baa38ba36c9
[sip-router] / test / udp.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2002-2003 Fhg Fokus
5  *
6  * This file is sipsak, a free sip testing tool.
7  *
8  * sipsak is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * sipsak is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18
19 /* sipsak written by nils ohlmeier (develop@ohlmeier.de).
20    based up on a modifyed version of shoot.
21    set DEBUG on compile will produce much more output. primarily
22    it will print out the sended and received messages before or after
23    every network action.
24 */
25
26 /* changes by jiri@iptel.org; now messages can be really received;
27    status code returned is 2 for some local errors , 0 for success
28    and 1 for remote error -- ICMP/timeout; can be used to test if
29    a server is alive; 1xx messages are now ignored; windows support
30    dropped
31 */
32
33 /*
34 shot written by ashhar farhan, is not bound by any licensing at all.
35 you are free to use this code as you deem fit. just dont blame the author
36 for any problems you may have using it.
37 bouquets and brickbats to farhan@hotfoon.com
38 */
39
40 /* TO-DO:
41    - support for short notation
42    - support for IPv6
43 */
44
45 //set ts=4 :-)
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <time.h>
54 #include <unistd.h>
55 #include <netdb.h>
56 #include <sys/socket.h>
57 #include <sys/utsname.h>
58
59 #include <regex.h>
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
62 #include <sys/poll.h>
63
64 #include <errno.h>
65
66 /* this is the main function with the loops and modes */
67 void shoot()
68 {
69         struct sockaddr_in      addr, sockname;
70         struct timeval  tv, sendtime, recvtime, firstsendt;
71         struct timezone tz;
72         struct pollfd sockerr;
73         int ssock, redirected, retryAfter;
74         int sock, i, len, ret, usrlocstep, randretrys;
75         int dontsend, cseqcmp, cseqtmp;
76         int rem_rand, rem_namebeg;
77         char *contact, *crlf, *foo, *bar;
78         fd_set  fd;
79         socklen_t slen;
80         regex_t redexp, proexp, okexp, tmhexp, errexp;
81         int bsd_compat, opt_size;
82
83         int nretries=3;
84         char *buff="MiniTest";
85
86
87         /* create a sending socket */
88         sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
89         if (sock==-1) {
90                 perror("no client socket");
91                 exit(2);
92         }
93
94
95 #ifndef _NO_LISTENER
96     /* create a listening socket */
97     ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
98     if (ssock==-1) {
99         perror("no server socket");
100         exit(2);
101     }
102
103     sockname.sin_family=AF_INET;
104     sockname.sin_addr.s_addr = htonl( INADDR_ANY );
105     sockname.sin_port = htons((short)47437);
106     if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
107         perror("no bind");
108         exit(2);
109     }
110 #endif
111
112
113         /* destination socket init here because it could be changed in a 
114            case of a redirect */
115         addr.sin_addr.s_addr = inet_addr("192.168.99.100");
116         addr.sin_port = htons((short)888);
117         addr.sin_family = AF_INET;
118
119         /* if we dont connect, even on Linux, nothing will happen */
120
121 #ifdef CONNECTED        
122         /* we connect as per the RFC 2543 recommendations
123            modified from sendto/recvfrom */
124         ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
125         if (ret==-1) {
126                 perror("no connect");
127                 exit(2);
128         }
129 #endif
130
131         if (getsockopt( sock, SOL_SOCKET, SO_BSDCOMPAT, &bsd_compat, &opt_size )==-1) {
132                 perror("ERROR");
133                 exit(1);
134         }
135         printf("BSD compat: %d\n", bsd_compat);
136
137         /* here we go for the number of nretries which healily depends on the 
138            mode */
139         for (i = 0; i <= nretries; i++)
140         {
141                 /* lets fire the request to the server and store when we did */
142
143                 /* if we send too fast, ICMP will arrive back when we are already
144                    done and we wont be able to recognize an error
145                 */
146 #ifdef CONNECTED
147                 ret = send(sock, buff, strlen(buff), 0);
148 #else
149                 ret=sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&addr, sizeof(addr));
150 #endif
151                 /* wait 1/10 sec to be safe we receive ICMP */
152                 usleep(100000);
153                 if (ret==-1) {
154                         perror("send failure");
155                         exit( 1 );
156                 }
157         }
158
159         exit(0);
160 }
161
162 int main(int argc, char *argv[])
163 {
164         shoot();
165 }
166