/
mtss-eng.c
180 lines (165 loc) · 7.14 KB
/
mtss-eng.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
/*
*
* Multi-Threaded web server using posix pthreads.
* Simple web server, capable of serving simple html,
* jpg, gif & text files.
*
* @created 20160826-01:22-GMT+1
* @modified 20160826-01:22-GMT+1
*
*/
//---Include files ------------------------------------------------------------
#include <stdio.h> // for printf()
#include <stdlib.h> // for exit()
#include <string.h> // for strcpy(),strerror() and strlen()
#include <fcntl.h> // for file i/o constants
#include <sys/stat.h> // for file i/o constants
#include <errno.h>
//---FOR BSD UNIX/LINUX -------------------------------------------------------
#include <sys/types.h> //
#include <netinet/in.h> //
#include <sys/socket.h> // for socket system calls
#include <arpa/inet.h> // for socket system calls (bind)
#include <sched.h>
#include <pthread.h> /* P-thread implementation */
#include <signal.h> /* for signaling */
#include <semaphore.h> /* for p-thread semaphores */
//---HTTP response messages ---------------------------------------------------
#define OK_IMAGE "HTTP/1.0 200 OKnContent-Type:image/gifnn"
#define OK_TEXT "HTTP/1.0 200 OKnContent-Type:text/htmlnn"
#define NOTOK_404 "HTTP/1.0 404 Not FoundnContent-Type:text/htmlnn"
#define MESS_404 "<html><body><h1>FILE NOT FOUND</h1></body></html>"
//---defines ------------------------------------------------------------------
#define BUF_SIZE 1024 // buffer size in bytes
#define PORT_NUM 6110 // Port number for a Web server (TCP 5080)
#define PEND_CONNECTIONS 100 // pending connections to hold
#define TRUE 1
#define FALSE 0
#define NTHREADS 5 /* Number of child threads */
#define NUM_LOOPS 10 /* Number of local loops */
#define SCHED_INTVL 5 /* thread scheduling interval */
#define HIGHPRIORITY 10
//---global variables ---------------------------------------------------------
sem_t thread_sem[NTHREADS];
int next_thread;
int can_run;
int i_stopped[NTHREADS];
unsigned int client_s; // Client socket descriptor.
//---child thread implementation ----------------------------------------------
void *my_thread(void * arg)
{
unsigned int myClient_s; //copy socket
// other local variables ------------------------------------------------------
char in_buf[BUF_SIZE]; // Input buffer for GET request.
char out_buf[BUF_SIZE]; // Output buffer for HTTP-response.
char *file_name; // File name.
unsigned int fh; // File handle (file descriptor).
unsigned int buf_len; // Buffer length for file reads.
unsigned int retcode; // Return code.
myClient_s = *(unsigned int *)arg; // Copy client socket descriptor.
//---receive the first HTTP request (HTTP GET) --------------------------------
retcode = recv(client_s, in_buf, BUF_SIZE, 0);
// if receive error.
if (retcode < 0)
{ printf("recv error detected ...n"); }
// if HTTP command successfully received.
else
{
// parse out the filename from GET request.
strtok(in_buf, " ");
file_name = strtok(NULL, " ");
// test for high priority file.
if(0 == strcmp(&file_name[1],"test_00.jpg")){
int diditwork = pthread_setschedprio(pthread_self(), HIGHPRIORITY);
if(!diditwork)
printf("priority wasn't increased correctly ...n");
else{
printf("High priority thread created ...n");
}
}
// open the requested file (start at 2nd char to get rid of leading "").
fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE);
// generate and send the response (404 if could not open the file).
if (fh == -1)
{
printf("File %s not found - sending an HTTP 404 n", &file_name[1]);
strcpy(out_buf, NOTOK_404);
send(client_s, out_buf, strlen(out_buf), 0);
strcpy(out_buf, MESS_404);
send(client_s, out_buf, strlen(out_buf), 0);
}
else
{
printf("File %s is being sent n", &file_name[1]);
if ((strstr(file_name, ".jpg") != NULL)||(strstr(file_name, ".gif") != NULL))
{ strcpy(out_buf, OK_IMAGE); }
else
{ strcpy(out_buf, OK_TEXT); }
send(client_s, out_buf, strlen(out_buf), 0);
buf_len = 1;
while (buf_len > 0)
{
buf_len = read(fh, out_buf, BUF_SIZE);
if (buf_len > 0)
{
send(client_s, out_buf, buf_len, 0);
// printf("%d bytes transferred ..n", buf_len);
}
}
close(fh); // close the file
close(client_s); // close the client connection
pthread_exit(NULL); // exit pthread, effectively killing off threads.
}
}
}
//===== Main program ========================================================
int main(void)
{
/* local variables for socket connection -------------------------------- */
unsigned int server_s; // Server socket descriptor
struct sockaddr_in server_addr; // Server Internet address
//unsigned int client_s; // Client socket descriptor
struct sockaddr_in client_addr; // Client Internet address
struct in_addr client_ip_addr; // Client IP address
int addr_len; // Internet address length
unsigned int ids; // holds thread args
pthread_attr_t attr; // pthread attributes
pthread_t threads; // Thread ID (used by OS)
/* create a new socket -------------------------------------------------- */
server_s = socket(AF_INET, SOCK_STREAM, 0);
/* fill-in address information, and then bind it ------------------------ */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
/* Listen for connections and then accept ------------------------------- */
listen(server_s, PEND_CONNECTIONS);
/* the web server main loop ============================================= */
pthread_attr_init(&attr);
while(TRUE)
{
printf("my server is ready ...n");
/* wait for the next client to arrive -------------- */
addr_len = sizeof(client_addr);
client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
printf("a new client arrives ...n");
if (client_s == FALSE)
{
printf("ERROR - Unable to create socket n");
exit(FALSE);
}
else
{
/* Create a child thread --------------------------------------- */
ids = client_s;
pthread_create ( /* Create a child thread */
&threads, /* Thread ID (system assigned) */
&attr, /* Default thread attributes */
my_thread, /* Thread routine */
&ids); /* Arguments to be passed */
}
}
/* To make sure this "main" returns an integer --- */
close (server_s); // close the primary socket
return (TRUE); // return code from "main"
}