-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathG.c
More file actions
139 lines (115 loc) · 4.45 KB
/
G.c
File metadata and controls
139 lines (115 loc) · 4.45 KB
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
// 2019 ARP assignment V2.0
// Andrea Pitto - S3942710
// 10 - 07 - 2020
// This process can be run in 2 modes: Debug mode (i.e. Single-machine - config.run_mode = 0) or
// Multi-machine mode (i.e.communicating with other PCs - config.run_mode = 1).
// In the first case it receives tokens from P, and then sends them back to it.
// In the other scenario, it sends data to the P of the next PC in the chain
#include "def.h"
int main(int argc, char *argv[])
{
close(atoi(argv[0]));
close(atoi(argv[1]));
close(atoi(argv[2]));
close(atoi(argv[4]));
close(atoi(argv[5]));
pid_t Gpid = getpid();
printf("G: my PID is %d\n", Gpid);
pid_t Parpid = getppid(); // get process ID of parent (i.e. main)
struct configuration config;
struct configuration *configPtr = &config;
char *configpath = "config"; // specify config file path
configLoader(configpath, configPtr);
int sockfd; // socket file descriptor
int newsockfd;
int portno; // port of the server for the client connection
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n; // read() handle
if (!config.run_mode) // config.run_mode = 0
{
token token;
token.value = 0;
gettimeofday(&token.timestamp, NULL); // get the current time and store it in timestamp
portno = LOCAL_PORT;
sockfd = socket(AF_INET, SOCK_STREAM, 0); // create a new socket
if (sockfd < 0)
error("\nError creating a new socket (G process)");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
error("\nG: setsockopt(SO_REUSEADDR) failed");
bzero((char *)&serv_addr, sizeof(serv_addr)); // the function bzero() sets all values inside a buffer to zero
serv_addr.sin_family = AF_INET; // this contains the code for the family of the address
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) // the bind() system call binds a socket to an address
error("\nError on binding");
// G process is now waiting for incoming tokens
listen(sockfd, MAX_REQS); // system call that allows this process to listen for connections over the socket
clilen = sizeof(cli_addr);
// The accept() system call causes the process to block until a client connects to the server
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen);
if (newsockfd < 0)
{
perror("\naccept() system call failed");
return -1;
}
else // connection accepted
{
while (1)
{
n = read(newsockfd, &token, sizeof(token));
if (n < 0)
error("\nError reading from socket");
write(atoi(argv[3]), &token, sizeof(token));
}
}
close(atoi(argv[3]));
}
else // config.run_mode = 1
{
char token[10]; // size 9 should be also fine
close(atoi(argv[3]));
mkfifo(config.fifo, 0644); // create a named pipe (grant full access to Owner, read only permission to Group and Other)
int fifofd = open(config.fifo, O_WRONLY);
portno = config.next_port;
sockfd = socket(AF_INET, SOCK_STREAM, 0); // create a new socket
if (sockfd < 0)
error("\nError creating a new socket (G process)");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
error("\nG: setsockopt(SO_REUSEADDR) failed");
bzero((char *)&serv_addr, sizeof(serv_addr)); // the function bzero() sets all values inside a buffer to zero
serv_addr.sin_family = AF_INET; // this contains the code for the family of the address
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) // the bind() system call binds a socket to an address
error("\nError on binding");
// G process is now waiting for incoming tokens
listen(sockfd, MAX_REQS); // system call that allows this process to listen for connections over the socket
clilen = sizeof(cli_addr);
// The accept() system call causes the process to block until a client connects to the server
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen);
if (newsockfd < 0)
{
perror("\naccept() system call failed");
return -1;
}
else // connection accepted
{
while (1)
{
// If main is dead, end the process
if (getppid() != Parpid)
{
unlink(config.fifo);
close(fifofd);
close(sockfd);
return 0;
}
n = read(newsockfd, &token, sizeof(token));
if (n < 0)
error("\nError reading from socket");
write(fifofd, &token, sizeof(token));
}
}
}
}