HTTP: Optimize request parser
[MonkeyD.git] / src / socket.c
blob1f6278bce82694235d6d6dd7eb94cf9c7ec62656
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2008-2009 Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <arpa/inet.h>
27 #include <netinet/tcp.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <string.h>
33 #include "socket.h"
34 #include "memory.h"
36 /*
37 * Example from:
38 * http://www.baus.net/on-tcp_cork
40 int mk_socket_set_cork_flag(int fd, int state)
42 return setsockopt(fd, SOL_TCP, TCP_CORK, &state, sizeof(state));
45 int mk_socket_set_nonblocking(int sockfd)
47 if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
48 perror("fcntl");
49 return -1;
51 return 0;
54 int mk_socket_set_tcp_nodelay(int sockfd)
56 int on=1;
57 return setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on));
60 char *mk_socket_get_ip(int socket)
62 int ipv4_len = 16;
63 socklen_t len;
64 char *ipv4;
65 struct sockaddr_in m_addr;
67 ipv4 = mk_mem_malloc(ipv4_len);
69 if(!ipv4)
71 return NULL;
74 len = sizeof(m_addr);
75 getpeername(socket, (struct sockaddr*)&m_addr, &len);
76 return (char *) inet_ntop(PF_INET, &m_addr.sin_addr, ipv4, ipv4_len);
79 int mk_socket_close(int socket)
81 return close(socket);
84 int mk_socket_timeout(int s, char *buf, int len,
85 int timeout, int recv_send)
87 fd_set fds;
88 time_t init_time, max_time;
89 int n=0, status;
90 struct timeval tv;
92 init_time=time(NULL);
93 max_time = init_time + timeout;
95 FD_ZERO(&fds);
96 FD_SET(s,&fds);
98 tv.tv_sec=timeout;
99 tv.tv_usec=0;
101 if(recv_send==ST_RECV)
102 n=select(s+1,&fds,NULL,NULL,&tv); // recv
103 else{
104 n=select(s+1,NULL,&fds,NULL,&tv); // send
107 switch(n){
108 case 0:
109 return -2;
110 break;
111 case -1:
112 //pthread_kill(pthread_self(), SIGPIPE);
113 return -1;
116 if(recv_send==ST_RECV){
117 status=recv(s,buf,len, 0);
119 else{
120 status=send(s,buf,len, 0);
123 if( status < 0 ){
124 if(time(NULL) >= max_time){
125 //pthread_kill(pthread_self(), SIGPIPE);
129 return status;
132 int mk_socket_create()
134 int sockfd;
136 if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
137 perror("client: socket");
138 return -1;
141 return sockfd;
144 int mk_socket_connect(int sockfd, char *server, int port)
146 int res;
147 struct sockaddr_in *remote;
149 remote = (struct sockaddr_in *)
150 mk_mem_malloc_z(sizeof(struct sockaddr_in));
151 remote->sin_family = AF_INET;
152 res = inet_pton(AF_INET, server, (void *)(&(remote->sin_addr.s_addr)));
154 if(res < 0)
156 perror("Can't set remote->sin_addr.s_addr");
157 mk_mem_free(remote);
158 return -1;
160 else if(res == 0){
161 perror("Invalid IP address\n");
162 mk_mem_free(remote);
163 return -1;
166 remote->sin_port = htons(port);
167 if (connect(sockfd,
168 (struct sockaddr *)remote,
169 sizeof(struct sockaddr)) == -1)
171 close(sockfd);
172 perror("client: connect");
173 return -1;
175 mk_mem_free(remote);
176 return 0;
179 void mk_socket_reset(int socket)
181 int status=1;
183 if(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&status,sizeof(int))==-1) {
184 perror("setsockopt");
185 exit(1);
189 /* Just IPv4 for now... */
190 int mk_socket_server(int port)
192 int fd;
193 struct sockaddr_in local_sockaddr_in;
195 /* Create server socket */
196 fd=socket(PF_INET,SOCK_STREAM,0);
197 mk_socket_set_tcp_nodelay(fd);
198 //mk_socket_set_nonblocking(fd);
200 local_sockaddr_in.sin_family=AF_INET;
201 local_sockaddr_in.sin_port=htons(port);
202 local_sockaddr_in.sin_addr.s_addr=INADDR_ANY;
203 memset(&(local_sockaddr_in.sin_zero),'\0',8);
205 /* Avoid bind issues, reset socket */
206 mk_socket_reset(fd);
208 if(bind(fd,(struct sockaddr *)&local_sockaddr_in,
209 sizeof(struct sockaddr)) != 0)
211 perror("bind");
212 printf("Error: Port %i cannot be used\n", port);
213 exit(1);
216 /* Listen queue:
217 * The queue limit is given by /proc/sys/net/core/somaxconn
218 * we need to add a dynamic function to get that value on fly
220 if((listen(fd, 1024))!=0) {
221 perror("listen");
222 exit(1);
225 return fd;