-
Notifications
You must be signed in to change notification settings - Fork 0
/
tutor.c
executable file
·283 lines (246 loc) · 6.61 KB
/
tutor.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
/*
* tutor.c: Server side code handles client/student requests
* This file is a part of Tutor
*
* Tutor is an application to create a tutor relationship tree using the client-server model.
* Consists of a tutor node (server) and many student nodes (clients).
* This was created as a part of CS 6390 Advanced Computer Networks course at UT Dallas.
*
* Contributors: Avinash Joshi <axj107420@utdallas.edu>, Sandeep Shenoy <sxs115220@utdallas.edu>
*/
#include "myheader.h"
const char *exec_name;
const char *com_list[] = {"help", "makeserver", "join", "computepath", "NULL"};
/* used for mapping the long options to short options */
const struct option long_options[] = {
{ "tport", required_argument, 0, 'p' },
{ "uport", required_argument, 0, 'P' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
/* Print the usage message */
static void
print_usage (void) {
fprintf (stdout, "usage: %s -p tcp_port -P udp_port [-h]\n", exec_name);
}
/* Print help message with all options */
static void
print_help (void) {
fprintf (stdout, "%s is an application to create tutor-student relationship tree\n", exec_name);
print_usage ();
fprintf (stdout, "\
-p, --tport <number> port number to be used with TCP\n\
-P, --uport <number> port number to be used with UDP\n\
-h, --help print this help\n");
}
/*
* This function checks if the string inputed
* is a number or not.
* Returns 1 if its a number else returns 0
*/
int
is_number (char * string) {
int temp = 0;
int is_num = 1;
while(string[temp] != 0) {
if(string[temp] < 48 || string[temp] > 57) is_num = 0;
temp++;
}
return is_num;
}
int
check_value (char *arg, char *opt) {
int num, n = 0;
if (strcmp ("k", opt) == 0)
n = 2;
if (strcmp ("port", opt) == 0)
n = 0;
if (!is_number (arg)) {
fprintf (stdout, "%s must be a number", arg);
return -1;
}
if ((num = atoi (arg)) < n) {
fprintf (stdout, "%s must be greater than %d", opt, n);
return -1;
}
return num;
}
/*
* atoint_cli = argument to number
* Function takes string as argument and returns
* a port number if the string has a "valid" number
* else exits the program with an FAILURE
*/
int
atoint_cli (char *arg, char opt) {
int num;
num = atoi(arg);
if (!is_number (arg) || num < 0) {
fprintf (stderr, "%s: %s: invalid number for argument -%c\n", exec_name, arg, opt);
print_usage ();
exit (EXIT_FAILURE);
}
return num;
}
int
is_command (char *com) {
int i = 0;
while (strcmp ("NULL", com_list[i]) != 0) {
if (strcmp (com, com_list[i]) == 0)
return 1;
i++;
}
return 0;
}
void
list_commands (void) {
int i = 0;
while (strcmp ("NULL", com_list[i]) != 0) {
fprintf (stdout, "%s ", com_list[i]);
i++;
}
fprintf (stdout, "\n");
}
int
main (int argc, char **argv) {
int optchar, opt_index = 0;
int pflag = 0, Pflag = 0;
int tport, uport, k;
char *tport_arg, *uport_arg;
char *in_line = (char *) malloc (sizeof (char) * 100);
char *command, *com_arg, *host;
int join_uport, join_status;
// Flags for the commands
int makeserver_f = 0, join_f = 0, computepath_f = 0;
/* strrchr gives the last occurance of PATH_SEPARATOR in argv[0] */
exec_name = strrchr (argv[0], PATH_SEPARATOR);
if (!exec_name)
exec_name = argv[0];
else
++exec_name;
/* Program must have atleast one argument */
if (argc < 2) {
print_usage ();
exit (EXIT_SUCCESS);
}
while ((optchar = getopt_long (argc, argv, "hp:P:", long_options, &opt_index)) != -1) {
switch (optchar) {
case 'p':
pflag = 1;
tport_arg = optarg;
break;
case 'P':
Pflag = 1;
uport_arg = optarg;
break;
case 'h':
print_help ();
return (EXIT_SUCCESS);
case '?':
default:
print_usage ();
return (EXIT_SUCCESS);
}
}
if (pflag == 0 || Pflag == 0) {
fprintf (stderr, "%s: -p and -P arguments are needed\n", exec_name);
print_usage ();
exit (EXIT_FAILURE);
}
tport = atoint_cli (tport_arg, 'p');
uport = atoint_cli (uport_arg, 'P');
node_number = 0;
bzero (in_line, 100);
DBG (("TCP Port: %d\t UDP Port: %d", tport, uport));
fprintf (stdout, "Howdy, fella. Looking to tutor?");
while (1) {
fprintf (stdout, "\ntutor> ");
fflush (stdin);
fgets (in_line, 100, stdin);
if (strcmp (in_line, "\n") == 0)
continue;
in_line [strlen (in_line) - 1] = '\0';
command = strtok (in_line, " ");
// Capture CTLR-D and exit
if (feof (stdin) || strcmp (command, "exit") == 0) {
exit (EXIT_SUCCESS);
}
// If command does not exist in the list
if (is_command (command) == 0) {
fprintf (stderr, "command %s does not exist. You may want to try help\n", command);
continue;
}
if (strcmp (command, "help") == 0) {
list_commands ();
continue;
}
if (strcmp (command, "makeserver") == 0) {
if (join_f == 1) {
fprintf (stdout, "You cannot make yourself as server after joining a node");
continue;
}
if (makeserver_f == 1) {
fprintf (stdout, "You are already a server");
continue;
}
com_arg = strtok (NULL, " ");
if (com_arg == NULL) {
fprintf (stdout, "makeserver takes one argument -- k value");
continue;
}
if ((k = check_value (com_arg, "k")) == -1)
continue;
DBG (("k value = '%d'", k));
makeserver_f = 1;
strcpy (parent.ip, "NULL");
create_udp (uport, tport, k);
create_tcp (tport, k);
fprintf (stdout, "Bound to UDP:%d TCP:%d", uport, tport);
continue;
}
if (strcmp (command, "join") == 0) {
com_arg = strtok (NULL, " ");
if (makeserver_f == 1) {
fprintf (stdout, "A server (root node) cannot join");
continue;
}
if (join_f == 1) {
fprintf (stdout, "You have already joined");
continue;
}
if (com_arg == NULL) {
fprintf (stdout, "join takes two argument <ipaddress | host> <udp-port>");
continue;
}
host = com_arg;
com_arg = strtok (NULL, " ");
if (com_arg == NULL) {
fprintf (stdout, "join takes two argument <ipaddress | host> <udp-port>");
continue;
}
if ((join_uport = check_value (com_arg, "port")) == -1)
continue;
join_status = join_tree (uport, tport, join_uport, 1234, host);
sleep (2);
if (join_status == -1)
continue;
join_f = 1;
fprintf (stdout, "You are now a tutor with ID:%d. Reach your instructor @ %s:%s", node_number, parent.ip, parent.tport);
continue;
}
if (strcmp (command, "computepath") == 0) {
computepath_f++;
if ((makeserver_f == 0) && (join_f == 0)) {
fprintf (stdout, "You can compute path only after 'makeserver' or 'join'");
continue;
}
if (strcmp (parent.ip, "NULL") == 0) {
fprintf (stdout, "You are the root node");
continue;
}
fprintf (stdout, "Computing path...");
compute_path();
}
}
return (EXIT_SUCCESS);
}