· 9 years ago · Oct 15, 2016, 03:10 AM
1/*
2
3
4 * mypingd.c
5 *
6 * Created on: Sep 17, 2016
7 * Author: prashantravi
8 */
9#define _DEFAULT_SOURCE
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <errno.h>
14#include <string.h>
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <arpa/inet.h>
19#include <netdb.h>
20#include <sys/time.h>
21#include <time.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <signal.h>
25
26typedef int bool;
27#define true 1
28#define false 0
29
30#define MAX_BUF 1000
31#define EXPECTED_RESPONSE "terve"
32#define TIME_OUT 550000
33#define INTERVAL 50000
34
35volatile bool received = false;
36volatile sig_atomic_t got_interrupt = 0;
37pid_t current_pid = -1 ;
38
39void make_alphanumeric_string(char *s, const int len);
40int sendPingRequest(char* hostname, char* hostUDPport, char* secretKey);
41void validateCommandLineArguments(int argc, char ** argv);
42void printTimeDifference(struct timeval *t1 , struct timeval *t2);
43void handle_signal_alarm(int sig);
44
45void handle_signal_alarm(int sig)
46{
47 int saved_errno = errno;
48 if (sig != SIGALRM) {
49 perror("Caught wrong signal\n");
50 }
51 if(received == false && got_interrupt++ == 40){
52 printf( "no response from ping server\n" );
53 kill(current_pid,SIGKILL);
54 }
55 errno = saved_errno;
56}
57
58
59void make_alphanumeric_string(char *s, const int len) {
60 static const char alphanum[] =
61 "0123456789"
62 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
63 "abcdefghijklmnopqrstuvwxyz";
64
65 int i;
66 for ( i = 0; i < len; ++i) {
67 s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
68 }
69 s[len] = 0;
70}
71
72void printTimeDifference(struct timeval *t1 , struct timeval *t2)
73{
74 struct timeval tv1 = *t1;
75 struct timeval tv2 = *t2;
76 long milliseconds;
77 milliseconds = (tv2.tv_usec - tv1.tv_usec) / 1000;
78 milliseconds += (tv2.tv_sec - tv1.tv_sec) *1000;
79 printf("Round trip time was : %3ld ms\n",milliseconds);
80}
81
82void validateCommandLineArguments(int argc, char ** argv)
83{
84 // Write this validation properly TODO
85 if(argc != 4)
86 {
87 printf("\nERROR! usage: %s receiver_hostname receiver_port secret_key\n\n", argv[0]);
88 exit(1);
89 }
90}
91
92
93int sendPingRequest(char* hostname, char* hostUDPport, char* secretKey)
94{
95 int sockfd;
96 struct addrinfo hints, *servinfo;
97 int rv;
98 int numbytes;
99
100 memset(&hints, 0, sizeof hints);
101 hints.ai_family = AF_INET;
102 hints.ai_socktype = SOCK_DGRAM;
103
104 if ((rv = getaddrinfo(hostname, hostUDPport, &hints, &servinfo)) != 0) {
105 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
106 return 2;
107 }
108
109 struct addrinfo *availableServerSockets = servinfo;
110 bool connectionSuccessful = false;
111 while(availableServerSockets != NULL)
112 {
113 bool error = false;
114
115 if ((sockfd = socket(availableServerSockets->ai_family, availableServerSockets->ai_socktype,availableServerSockets->ai_protocol)) == -1) {//If it fails...
116 error = true;
117 }
118 if(error)
119 availableServerSockets = availableServerSockets->ai_next;
120 else
121 {
122 connectionSuccessful = true;
123 break;
124 }
125 }
126
127 if(!connectionSuccessful)
128 {
129 printf("Could not connect to host \n");
130 return 2;
131 }
132 else
133 {
134 // Successfully connected to server
135 }
136 int tr = 1;
137 setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tr, sizeof(int));
138
139 // Construct message with format $secretKey$pad to be 1000 bytes
140 char str[MAX_BUF];
141 //Get length of secret key.
142 int dlen = (strlen(secretKey)) * sizeof(char);
143 sprintf(str, "$%s$", secretKey);
144 dlen = dlen + 2*sizeof(char);
145 //Find how many alphanumeric characters we need to pad
146 int dpad = MAX_BUF - dlen;
147 //Our final sending buffer
148 char fSendBuffer[MAX_BUF] = {0};
149 memcpy(fSendBuffer, str , dlen);
150 make_alphanumeric_string(fSendBuffer+dlen, dpad );
151
152 char recv_response[6];
153 struct timeval tv1;
154 struct timezone tz1;
155 struct timeval tv2;
156 struct timezone tz2;
157 struct sockaddr_in from;
158 socklen_t addr_len = sizeof from;
159 socklen_t sin_size = sizeof(struct sockaddr);
160 signal(SIGALRM, handle_signal_alarm);
161 ualarm(TIME_OUT,INTERVAL);
162 if (-1 == gettimeofday(&tv1, &tz1)) {
163 perror("resettimeofday: gettimeofday");
164 exit(-1);
165 }
166 if(sendto(sockfd, fSendBuffer, strlen(fSendBuffer), 0, availableServerSockets->ai_addr, availableServerSockets->ai_addrlen) == -1)
167 {
168 perror("sendto: failed\n");
169 }
170 socklen_t addrlen = sizeof(from); /* must be initialized */
171 recvfrom(sockfd, recv_response, sizeof(recv_response), 0, (struct sockaddr *)&from, &addrlen);
172 received = true;
173 if (-1 == gettimeofday(&tv2, &tz2)) {
174 perror("resettimeofday: gettimeofday");
175 exit(-1);
176 }
177 recv_response[5] = '\0';
178 struct hostent *hostp; /* server host info */
179 hostp = gethostbyaddr((const char *)&from.sin_addr.s_addr,
180 sizeof(from.sin_addr.s_addr), AF_INET);
181 if (hostp == NULL)
182 perror("ERROR on gethostbyaddr");
183 char *hostaddrp; /* dotted decimal server host addr string */
184 hostaddrp = inet_ntoa(from.sin_addr);
185 if (hostaddrp == NULL)
186 perror("ERROR on inet_ntoa\n");
187 if(strcmp(EXPECTED_RESPONSE, recv_response ) == 0)
188 {
189 printTimeDifference(&tv1, &tv2);
190 }
191 else
192 printf("Packet received was corrupt : %s\n", recv_response);
193 printf("Client received datagram from %s (%s)\n",hostp->h_name, hostaddrp);
194 close(sockfd);
195 return EXIT_SUCCESS;
196}
197
198int main(int argc, char** argv)
199{
200 validateCommandLineArguments(argc, argv);
201 current_pid = getpid();
202 return sendPingRequest(argv[1], argv[2], argv[3]);
203}