-
Notifications
You must be signed in to change notification settings - Fork 2
/
mailutils.c
256 lines (196 loc) · 5.75 KB
/
mailutils.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
///////////////////////////////////////////////////////////////////////////////
//
// File Name: mailutils.c
// Description: This file contains methods to used by both client and server.
// Author: Santosh K Tadikonda, stadikon@gmu.edu
// Date: Dec 1, 2013
// Version: 1.0
//
///////////////////////////////////////////////////////////////////////////////
// include files
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include "common.h"
#define MAXNAMELEN 256
void printpkt(Packet *);
// prepare server to accept requests
// returns file descriptor of socket
// returns -1 on error
int startserver() {
// fprintf(stderr, "Method Entry: startserver()\n");
int sd;
char * servhost;
ushort servport;
// create a TCP socket using socket()
sd = socket(PF_INET, SOCK_STREAM, 0);
// bind the socket to some port using bind()
// let the system choose a port
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(5945);
// Set this so that no issues if port already blocked.
int optval = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
bind(sd, (struct sockaddr *) &server_address, sizeof(server_address));
// we are ready to receive connections
listen(sd, 5);
// figure out the full local host name (servhost)
// use gethostname() and gethostbyname()
// full host name is zeus.ite.gmu.edu instead of just zeus
char hostname[MAXNAMELEN];
if (gethostname(hostname, sizeof hostname) != 0)
perror("gethostname");
struct hostent* h;
h = gethostbyname(hostname);
// figure out the port assigned to this server (servport)
// use getsockname()
int len = sizeof(struct sockaddr);
getsockname(sd, (struct sockaddr *) &server_address, &len);
servhost = h->h_name;
servport = ntohs(server_address.sin_port);
// ready to accept requests
fprintf(stderr,
"Welcome to Santosh's E-mail Server running on host %s, port %hu\n",
servhost, servport);
return (sd);
}
// establishes connection with the server
// returns file descriptor of socket
// returns -1 on error
int hooktoserver(char* user, char* servhost, ushort servport) {
//printf("hooktoserver(%s, %s, %hu)\n", user, servhost,
// servport);
int sd;
// create a TCP socket using socket()
sd = socket(AF_INET, SOCK_STREAM, 0);
// connect to the server on 'servhost' at 'servport'
// use gethostbyname() and connect()
// struct hostent *hostinfo;
struct sockaddr_in address;
// hostinfo = gethostbyname(servhost);
// address.sin_addr = *(struct in_addr *) &servhost;
address.sin_family = AF_INET;
address.sin_port = htons(servport);
inet_pton(AF_INET, servhost, &address.sin_addr);
// printf("Connecting..\n");
if (connect(sd, (struct sockaddr *) &address, sizeof(address)) < 0) {
perror("connecting");
exit(1);
}
// printf("Connected..\n");
return (sd);
}
// receives n bytes on the given socket into the buffer.
int readn(int sd, char *buf, size_t n) {
// printf("readn via utils. %d, %d\n", sd, n);
size_t toberead = n;
char * ptr = buf;
while (toberead > 0) {
int errno_save = 0;
// fprintf(stderr, "toberead: %zu\n", toberead);
ssize_t byteread = read(sd, ptr, toberead);
errno_save = errno;
// fprintf(stderr, "toberead: %zu, byteread: %zd\n", toberead, byteread);
if (byteread <= 0) {
// fprintf(stderr, "byteread val: %d",byteread);
if (byteread == -1)
{
perror("read");
errno = errno_save;
}
return (0);
}
toberead -= byteread;
ptr += byteread;
}
// fprintf(stderr, "Finished readn. %s\n", buf);
return (1);
}
// receives a packet on the given socket.
Packet *recvpkt(int sd)
{
// printf("Recvpkt via utils.\n");
Packet *pkt;
// allocate space for the pkt
pkt = (Packet *) calloc(1, sizeof(Packet));
if (!pkt) {
fprintf(stderr, "error : unable to calloc\n");
return(NULL);
}
// read the message type
if (!readn(sd, (char *) &pkt->type, sizeof(pkt->type))) {
free(pkt);
return(NULL);
}
// read the message length
if (!readn(sd, (char *) &pkt->lent, sizeof(pkt->lent))) {
free(pkt);
return(NULL);
}
pkt->lent = ntohl(pkt->lent);
// allocate space for message text
if (pkt->lent > 0) {
pkt->text = (char *) malloc(pkt->lent + 1);
if (!pkt) {
fprintf(stderr, "error : unable to malloc\n");
return(NULL);
}
// read the message text
if (!readn(sd, pkt->text, pkt->lent)) {
freepkt(pkt);
return(NULL);
}
pkt->text[pkt->lent] = '\0';
}
// fprintf(stderr, "Reading packet complete succesfully. %s\n", pkt->text);
// printpkt(pkt);
return(pkt);
}
// Sends a packet on given socket with given type, length and data.
int sendpkt(int sd, uint8_t typ, uint32_t len, char *buf)
{
//fprintf(stderr, "Send packet via utils. sd: %d, typ: %u, len: %lu, buf: %s\n", sd, typ, len, buf);
char tmp[8];
uint32_t siz;
// write type and lent
bcopy(&typ, tmp, sizeof(typ));
siz = htonl(len);
bcopy((uint32_t *) &siz, tmp+sizeof(typ), sizeof(len));
write(sd, tmp, sizeof(typ) + sizeof(len));
//* write message text
if (len > 0)
write(sd, buf, len);
return(1);
}
// free memory of a given packet.
void freepkt(Packet *pkt)
{
// fprintf(stderr, "Freeing packet.\n");
free(pkt->text);
free(pkt);
}
// display data in the given packet.
void printpkt(Packet *pkt)
{
fprintf(stderr, "Printing packet.\n");
fprintf(stderr, "pkt -> type: %u\n", pkt->type);
fprintf(stderr, "pkt -> len: %d\n", pkt->lent);
fprintf(stderr, "pkt -> text: %s\n", pkt->text);
}
///////////////////////////////////////////////////////////////////////////////