-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserverMessageHandler.c
More file actions
153 lines (136 loc) · 6.85 KB
/
serverMessageHandler.c
File metadata and controls
153 lines (136 loc) · 6.85 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
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdint.h>
#include "handleTable.h"
#include "PDUTransmit.h" //wrapper for safeUtil, attaches PDUs to messages
#include "safeUtil.h"
//Functions for handling each flag
void handleClientInit(int clientSocket, struct PDUMsg* dataBuffer); //FLAG_CLIENT_INITIAL -handles init msg from client (handles client requesting handle name)
void sendBroadcast(int clientSocket, struct PDUMsg* dataBuffer); //FLAG_BROADCAST_MESSAGE -handles client requesting to broadcast a message
void forwardMultiCast(int clientSocket, struct PDUMsg* dataBuffer); //FLAG_DIRECT_MESSAGE or FLAG_MULTICAST_MESSAGE -handles sending a unicast or multicast message. (unicast msgs have same format as multicast)
void sendHandlerList(int clientSocket, struct PDUMsg* dataBuffer); //FLAG_REQUEST_HANDLE_LIST -handles client requesting the handler list
//calls the appropriate function for handling the packet based on the flag (byte 0)
//removes the flag byte when passing the messageLen and dataBuffer to the appropriate function
void handleMessage(int clientSocket, struct PDUMsg* msg){
//match the flag with the correct type of message:
switch (msg->flag) {
case FLAG_CLIENT_INITIAL:
handleClientInit(clientSocket, msg);
break;
case FLAG_BROADCAST_MESSAGE:
sendBroadcast(clientSocket, msg);
break;
case FLAG_DIRECT_MESSAGE:
forwardMultiCast(clientSocket, msg); //direct and MultiCast message format are the same
break;
case FLAG_MULTICAST_MESSAGE:
forwardMultiCast(clientSocket, msg);
break;
case FLAG_REQUEST_HANDLE_LIST:
sendHandlerList(clientSocket,msg);
break;
default:
printf("Warning, Unrecognized Flag, disregarding msg\n");
break;
}
}
//handles client initialization. checks if the client handle is in use. sends a flag for accepted or rejected (if handle name alr in use)
void handleClientInit(int clientSocket, struct PDUMsg* msg){
uint16_t h_msgLen= ntohs(msg->nw_length);
if(h_msgLen-DataOffset<2){ //minimum of 1 byte handleLength, 1 byte handle, is needed for this flag to be accepted.
printf("Warning, Client init message has too little data. Disregarding this message\n");
return;
}
uint8_t handleLength=msg->data[0]; //first byte handler length
char* handleName=((char*) msg->data )+1; //following bytes are the handler message
struct handlerEntry newEntry= {
.handleName = handleName,
.handleSize = handleLength,
.socketNo = clientSocket
};
if (handleTable_push(newEntry)==-1){ //Unable to add entry, we need send failure message
sendResponseFlag(clientSocket, FLAG_SEND_REJECTED);
} else{
sendResponseFlag(clientSocket, FLAG_SEND_ACCEPTED);
}
}
//forwards a client's broadcast message to everyone except themself
void sendBroadcast(int clientSocket, struct PDUMsg* dataBuffer){
int numHandles=handleTable_getLength();
uint16_t h_bufferLen=ntohs(dataBuffer->nw_length);
for(int i=0;i<numHandles;i++){ //iterate over each handle to send them the broadcast
int socketNo= handleTable_getEntry_socketNo(i);
if(socketNo!=clientSocket){ //do not send the client there own broadcast
safeSend(socketNo, (uint8_t*)dataBuffer, h_bufferLen,0); //forward message directly as is, dont attach PDU
}
}
return;
}
//handles sending a unicast or multicast message. (unicast msgs have same format as multicast)
void forwardMultiCast(int clientSocket, struct PDUMsg* dataBuffer){
uint8_t sendersLength=(dataBuffer->data) [0]; //first bit contains length of sender
uint16_t h_bufferLen=ntohs(dataBuffer->nw_length);
if(sendersLength+1>=h_bufferLen){
printf("Warning: invalid sender handler length (too long for msg size). This should never happen\n");
return;
}
int targetHandlerIndex=sendersLength+1; //index where target clients info begins
if (targetHandlerIndex >= h_bufferLen) {
printf("Warning: no space for numTargets byte in multi cast msg. aborting\n");
return;
}
uint8_t numTargets=(dataBuffer->data)[targetHandlerIndex]; //retrieve number of targets
targetHandlerIndex++; //Point to start of target handlers
for(int i=0;i<numTargets;i++){ //iterate over each target
uint8_t targetSocketLen=(dataBuffer->data)[targetHandlerIndex];
if(targetHandlerIndex+targetSocketLen>h_bufferLen){
printf("warning, multicast iteration exceeded end of dataBuffer msg according to its self proclaimed size. This should never happen\n");
return;
}
targetHandlerIndex++; //move to the actual name
char* targetName=(char*) &((dataBuffer->data)[targetHandlerIndex]);
int targetSocketNo;
if((targetSocketNo =handleTableNameToSocket(targetName, targetSocketLen)) ==-1){ //retrieve matching socketNo
//if the socketNo doesn't exist, send error msg to client
sendPDUWithFlag(clientSocket, FLAG_INVALID_HANDLE, ((uint8_t*)targetName)-1, ((int)targetSocketLen)+1);
//^^include the length of the name at start of data
}else{
//the target Exists, forward the message to them
safeSend(targetSocketNo, (uint8_t*)dataBuffer,h_bufferLen,0); //forward message exactly as is, it already contains PDU
}
targetHandlerIndex+=targetSocketLen;
}
}
//helper function for sendHandlerList
void sendHandlerName(int clientSocket, char* handleName, uint8_t handleSize);
//sends the SOF for the list, then send each name. then sends and end of frame
void sendHandlerList(int clientSocket, struct PDUMsg* dataBuffer){
uint32_t numHandles=handleTable_getLength();
uint32_t nw_numHandles=htonl(numHandles);
//send msg indicating number of handles to client
sendPDUWithFlag(clientSocket,FLAG_SEND_LIST_COUNT,(uint8_t*)(&nw_numHandles),sizeof(uint32_t));
for(int i=0;i<numHandles;i++){ //iterate over each of the handles to send to the client
char* handleName=handleTable_getEntry_handleName(i);
uint8_t handleSize=handleTable_getEntry_handleSize(i);
sendHandlerName(clientSocket, handleName, handleSize); //send the handler
}
//send terminated message, indicating the list is over
sendResponseFlag(clientSocket, FLAG_SEND_LIST_DONE);
}
void sendHandlerName(int clientSocket, char* handleName, uint8_t handleSize){
uint8_t dataBuffer[handleSize+1];
dataBuffer[0]=handleSize;
memcpy(dataBuffer+1,handleName, handleSize);
sendPDUWithFlag(clientSocket, FLAG_SEND_LIST_ENTRY,dataBuffer,handleSize+1);
}