src/server/httplistener.c

changeset 1
3c066d52342d
child 4
998844b5ed25
equal deleted inserted replaced
0:4c89c7683fb6 1:3c066d52342d
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2011 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "nsapi.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <sys/shm.h>
35 #include <sys/types.h>
36 #include <sys/ipc.h>
37 #include <sys/socket.h>
38 #include <sys/file.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <strings.h>
46 #include <stdbool.h>
47 #include <pthread.h>
48
49 #include "map.h"
50 #include "httplistener.h"
51
52 #include "session.h"
53
54 hashmap_t *listener_map = NULL;
55
56
57 int start_all_listener() {
58 HttpListener *listener = get_http_listener("default");
59 http_listener_start(listener);
60
61 return 0;
62 }
63
64 HttpListener* get_http_listener(char *name) {
65 return hashmap_get(listener_map, sstr(name));
66 }
67
68
69 HttpListener* http_listener_new(ListenerConfig *conf) {
70 HttpListener *listener = malloc(sizeof(HttpListener));
71 listener->session_handler = create_basic_session_handler();
72 listener->nacceptors = conf->nacceptors;
73
74 struct sockaddr_in servaddr; /* server address */
75
76 /* init address structure */
77 memset(&servaddr, 0, sizeof(servaddr));
78 servaddr.sin_family = AF_INET;
79 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
80 servaddr.sin_port = htons(conf->port);
81
82 /* create socket */
83 if((listener->server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
84 perror("Error: http_listener_new: socket");
85 return NULL;
86 }
87
88 int o = 1;
89 setsockopt(
90 listener->server_socket,
91 SOL_SOCKET, SO_REUSEADDR,
92 &o,
93 sizeof(int));
94
95 /* bind server socket to address */
96 if(bind(listener->server_socket, (struct sockaddr*)&servaddr, sizeof(servaddr))){
97 perror("Error: http_listener_new: bind");
98 return NULL;
99 }
100
101 /* create acceptors */
102 listener->acceptors = calloc(listener->nacceptors, sizeof(void*));
103 for (int i=0;i<listener->nacceptors;i++) {
104 listener->acceptors[i] = acceptor_new(listener);
105 }
106
107 if(listener_map == NULL) {
108 listener_map = hashmap_new(8);
109 }
110 hashmap_put(listener_map, sstr(conf->name), listener);
111 return listener;
112 }
113
114 int http_listener_start(HttpListener *listener) {
115 printf("INFO: start listener\n");
116
117 if (listen(listener->server_socket, 16) == -1) {
118 perror("Error: http_listener_start: listen");
119 return -1;
120 }
121
122 /* start acceptor threads */
123 for (int i=0;i<listener->nacceptors;i++) {
124 acceptor_start(listener->acceptors[i]);
125 }
126 }
127
128
129
130 Acceptor* acceptor_new(HttpListener *listener) {
131 Acceptor *acceptor = malloc(sizeof(Acceptor));
132 acceptor->listener = listener;
133 return acceptor;
134 }
135
136 void acceptor_start(Acceptor *a) {
137 if(pthread_create(
138 &a->tid,
139 NULL,
140 (void*(*)(void*))acceptor_thread,
141 a) != 0)
142 {
143 perror("Error: acceptor_start: pthread_create");
144 }
145 }
146
147 void* acceptor_thread(Acceptor *acceptor) {
148 HttpListener *listener = acceptor->listener;
149
150 for (;;) {
151 /* accept connections */
152 struct sockaddr_in ca;
153 int length = sizeof(ca);
154 int clientfd;
155
156 /* accept a connection */
157 clientfd = accept(
158 listener->server_socket,
159 (struct sockaddr*)&ca,
160 &length);
161 if (clientfd == -1) {
162 perror("Error: acceptor_thread: accept");
163 continue;
164 }
165
166 /* create Connection object */
167 Connection *conn = malloc(sizeof(Connection));
168 conn->address = ca;
169 conn->fd = clientfd;
170
171 /* enqueue the connection */
172 listener->session_handler->enqueue_connection(
173 listener->session_handler,
174 conn);
175
176 /* ready for new connection */
177 }
178 }

mercurial