-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommunicationprotocol.c
More file actions
212 lines (205 loc) · 6.07 KB
/
Copy pathcommunicationprotocol.c
File metadata and controls
212 lines (205 loc) · 6.07 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
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
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define PREFIX 0x23107231
#define ERROR_MSG_OPERATION 3
#define FACE_DETECT 0
#define FACE_REPLACE 1
#define OUTPUT_IMAGE 2
#define INCORECT_PREFIX_ERROR 13
#define BAD_OPER 12
#define COMMUNICATION_ERROR 14
#define BUFFER_SIZE 1024
/* this struct defines the way a protocol message will be structured
*/
typedef struct {
int requestType;
char* fileMessage;
size_t fileLen;
char* replaceFile;
size_t replaceLen;
} Feedback;
/* This struct defines the requirment to create a protocol structured message
*/
typedef struct {
FILE* stream;
uint8_t operType;
FILE* image;
FILE* sImage;
} Payload;
/* recive_payload()
* ---------------
* this function is to recive files that are structured correctly according to
* the protocol from a pipe and store it as a list of characters.
*
* storingLocation: the a pointer to the list which is the location that the
* list of chars will end up with
* outLen: the pointer to the a place to store the size of file as reported by
* the sender
* from: the pipe to read the image from
*
* RETURNS:
* 1: if there was an issue will reading the file and the size
* 0: if there no errors in reading
*/
int recive_payload(char** storingLocation, size_t* outLen, FILE* from)
{
uint32_t size;
// by the protcol the size will come first
size_t s = fread(&size, sizeof(uint32_t), 1, from);
if (s != 1) {
return 1;
}
// size is use make enough space for the incoming file
*storingLocation = malloc(size);
size_t image = fread(*storingLocation, 1, size, from);
if (image < size) {
return 1;
}
*outLen = size;
return 0;
}
/* recive_message()
* ----------------
* handles the reciving of a message down a pipe from a file discrpter and
* checks for validity agianst the communciation protocol.
*
* from: this is the pipe that will get the message
*
* RETURNS:
* a feedback stuct filled with all the details about the request that the user
* sent. if there was any faluire it is all reported in the struct's requestType
* if the requestType is set to:
* 14: then the message was incomplete and there was communication error
* 13: then the message sent had an incorrect prefix
* 12: then the message had an unrecognised operation type
* 0: for a sucessfull, complete message
*/
Feedback recive_message(FILE* from)
{
uint32_t prefix;
uint8_t operType;
Feedback feedback = {0};
// prefix comes first
size_t s = fread(&prefix, sizeof(uint32_t), 1, from);
if (s != 1) {
// incomplete prefix not incorrect
feedback.requestType = COMMUNICATION_ERROR;
return feedback;
}
if (prefix != (uint32_t)PREFIX) {
feedback.requestType = INCORECT_PREFIX_ERROR;
return feedback;
}
s = fread(&operType, sizeof(uint8_t), 1, from);
if (s != 1) {
feedback.requestType = COMMUNICATION_ERROR;
return feedback;
}
if (operType != (uint8_t)OUTPUT_IMAGE && operType != (uint8_t)FACE_REPLACE
&& operType != (uint8_t)FACE_DETECT
&& operType != (uint8_t)ERROR_MSG_OPERATION) {
// unrecognised operation
feedback.requestType = BAD_OPER;
return feedback;
}
feedback.requestType = operType;
if (recive_payload(&feedback.fileMessage, &feedback.fileLen, from)) {
// recive payload reported and error
feedback.requestType = COMMUNICATION_ERROR;
return feedback;
}
if (operType == (uint8_t)FACE_REPLACE) {
if (recive_payload(&feedback.replaceFile, &feedback.replaceLen, from)) {
feedback.requestType = COMMUNICATION_ERROR;
return feedback;
}
}
return feedback;
}
/* send_file()
* -----------
* this function will send a file to the specfied pipe and will send the size
* of before the file is sent if specfied.
*
* to: the pipe to send the file to
* stream: the file to send down the pipe
* sendSize: if set to a non zero number will send the size before the file
*
* RETURNS:
* 1: if there was a faluire to write the files to the pipe
* 0: if the opperation was a sucess
*/
int send_file(FILE* to, FILE* stream, int sendSize)
{
ssize_t got;
size_t lenI = 0;
char buffer[BUFFER_SIZE];
char* bytes = NULL;
while ((got = fread(buffer, 1, BUFFER_SIZE, stream)) > 0) {
bytes = realloc(bytes, lenI + got);
for (int i = 0; i < got; i++) {
bytes[lenI + i] = buffer[i];
}
lenI += got;
if (got < BUFFER_SIZE) {
break;
}
}
uint32_t size = (uint32_t)lenI;
if (sendSize) {
if (fwrite(&size, sizeof(uint32_t), 1, to) != 1) {
free(bytes);
return 1;
}
fflush(to);
}
if (fwrite(bytes, 1, size, to) != size) {
free(bytes);
return 1;
}
fflush(to);
free(bytes);
return 0;
}
/* send_payload()
* --------------
* this function will send the protocol structured message based on the provided
* pointer to the struct payload
*
* payload: the pointer to the struct that includes all the nescesary detials to
* send the message including who and what
*
* RETURNS:
* 0: if there was in trying to communicat with the reciver
* 1: if there sending the information was a sucess
*/
int send_payload(Payload* payload)
{
uint32_t prefix = PREFIX;
if (fwrite(&prefix, sizeof(uint32_t), 1, payload->stream) != 1) {
// there was an issue while writing
return 1;
}
fflush(payload->stream);
if (fwrite(&payload->operType, sizeof(uint8_t), 1, payload->stream) != 1) {
return 1;
}
fflush(payload->stream);
switch ((int)payload->operType) {
case FACE_REPLACE:
if (send_file(payload->stream, payload->image, 1)) {
return 1;
}
if (send_file(payload->stream, payload->sImage, 1)) {
return 1;
}
break;
default:
// this case is sending error messages, files and error messages
if (send_file(payload->stream, payload->image, 1)) {
return 1;
}
}
return 0;
}