-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.c
196 lines (167 loc) · 5.65 KB
/
server.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
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include "hashmap.h"
#define DEFAULT_PORT 11211
#define HEADER_LENGTH 24
struct packet {
unsigned char magic;
unsigned char opcode;
unsigned char key_length[2];
unsigned char extras_length;
unsigned char data_type;
unsigned char reserverd_or_status[2];
unsigned char total_body_length[4];
unsigned char opaque[4];
unsigned char cas[8];
};
void *client_thread(void *arg) {
int conn_socket;
int err;
memcpy(&conn_socket, arg, sizeof(int));
// conn_socket = * ((int *) arg);
pthread_detach(pthread_self());
for ( ; ; ) {
struct packet *recv_packet = malloc(HEADER_LENGTH);
bzero(recv_packet, HEADER_LENGTH);
err = read(conn_socket, (void *)recv_packet, HEADER_LENGTH);
if (err == 0) {
printf("TCP FIN! Close and return thread\n");
free(recv_packet);
close(conn_socket);
return NULL;
}
// getter
if (recv_packet->opcode == 0) {
int key_length = recv_packet->key_length[1] | recv_packet->key_length[0] << 8;
char *recv_key;
char *value;
struct packet send_packet;
recv_key = malloc(key_length+1);
bzero(recv_key, key_length);
err = read(conn_socket, recv_key, key_length);
recv_key[key_length] = '\0';
printf("it is a get, key is %s\n", recv_key);
value = map_get(recv_key);
bzero(&send_packet, sizeof(struct packet));
send_packet.magic = 0x81;
send_packet.opcode = 0x00;
if (value != NULL) {
// found a value
printf("found a value: %s\n", value);
int value_length = strlen(value);
int body_length = value_length + 4;
char send_buffer[sizeof(struct packet) + value_length + 4];
char extras[4] = {0x00, 0x00, 0x00, 0x00};
bzero(send_buffer, sizeof(struct packet) + value_length);
send_packet.reserverd_or_status[0] = 0x00;
send_packet.reserverd_or_status[1] = 0x00;
send_packet.extras_length = 4 & 0xFF;
send_packet.total_body_length[3] = body_length & 0xFF;
send_packet.total_body_length[2] = body_length >> 8 & 0xFF;
send_packet.total_body_length[1] = body_length >> 16 & 0xFF;
send_packet.total_body_length[0] = body_length >> 24 & 0xFF;
// send_packet.cas[7] = 1 & 0xFF;
// send_packet.total_body_length = (char *)&value_length;
memcpy(send_buffer, &send_packet, HEADER_LENGTH);
memcpy(send_buffer+HEADER_LENGTH, extras, 4);
memcpy(send_buffer+HEADER_LENGTH+4, value, value_length);
write(conn_socket, (void *)send_buffer, sizeof(send_buffer));
}
else {
// not found
printf("not found!\n");
char send_buffer[sizeof(struct packet) + 9];
bzero(send_buffer, sizeof(struct packet) + 9);
send_packet.reserverd_or_status[0] = 0x00;
send_packet.reserverd_or_status[1] = 0x01;
send_packet.total_body_length[3] = 9 & 0xFF;
memcpy(send_buffer, &send_packet, HEADER_LENGTH);
memcpy(send_buffer+HEADER_LENGTH, "Not found", 9);
write(conn_socket, (void *)send_buffer, sizeof(send_buffer));
}
free(recv_key);
}
// setter
else if (recv_packet->opcode == 1) {
struct packet send_packet;
int key_length = recv_packet->key_length[1] | recv_packet->key_length[0] << 8;
int extras_length = recv_packet->extras_length;
int body_length = recv_packet->total_body_length[3] | recv_packet->total_body_length[2] << 8
| recv_packet->total_body_length[1] << 16 | recv_packet->total_body_length[0] << 24;
int value_length = body_length-extras_length-key_length;
char *key = malloc(key_length+1);
char *extra = malloc(extras_length+1);
char *value = malloc(value_length+1);
bzero(key, key_length);
bzero(extra, extras_length);
bzero(value, value_length);
key[key_length] = '\0';
value[value_length] = '\0';
err = read(conn_socket, extra, extras_length);
err = read(conn_socket, key, key_length);
err = read(conn_socket, value, value_length);
printf("it is a set: key: %s, value: %s\n", key, value);
map_set(key, value);
bzero(&send_packet, sizeof(struct packet));
send_packet.magic = 0x81;
send_packet.opcode = 0x01;
send_packet.reserverd_or_status[0] = 0x00;
send_packet.reserverd_or_status[1] = 0x00;
write(conn_socket, (void *)&send_packet, sizeof(send_packet));
free(key);
free(extra);
free(value);
}
free(recv_packet);
}
}
int main(int argc, char **argv) {
int listen_socket, conn_socket;
struct sockaddr_in servaddr;
int err;
// init the map data structure
map_init();
// map_set("key1", "value");
// map_set("key2", "value");
// // map_print();
// map_set("key3", "value");
// // map_print();
// map_set("key2", "xfa");
// map_print();
// printf("get %s\n", map_get("key2"));
// return 1;
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket < 0) {
printf("error creating socket!\n");
}
bzero (&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(DEFAULT_PORT);
// bind socket to all the interfaces.
err = bind(listen_socket, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (err < 0) {
printf("error binding socket!\n");
}
printf("server is running at port 11211\n");
err = listen(listen_socket, 5);
for ( ; ; ) {
struct sockaddr_in cliaddr;
pthread_t thread_id;
socklen_t clilen = sizeof(cliaddr);
printf("waiting for connection\n");
conn_socket = accept(listen_socket, (struct sockaddr *) &cliaddr, &clilen);
printf("accept socket conn\n");
// once we accepted the connection, create a thread to handle the response.
err = pthread_create(&thread_id, NULL, &client_thread, &conn_socket);
if (err < 0) {
printf("error creating thread\n");
}
}
}