正在显示
1 个修改的文件
包含
260 行增加
和
0 行删除
src/server/spserver/spioutils.cpp
0 → 100644
1 | +/* | ||
2 | + * Copyright 2007 Stephen Liu | ||
3 | + * For license terms, see the file COPYING along with this library. | ||
4 | + */ | ||
5 | + | ||
6 | +#include <stdio.h> | ||
7 | +#include <fcntl.h> | ||
8 | +#include <errno.h> | ||
9 | +#include <string.h> | ||
10 | +#include <assert.h> | ||
11 | +#include <sys/types.h> | ||
12 | +#include <sys/stat.h> | ||
13 | + | ||
14 | +#include "spporting.hpp" | ||
15 | + | ||
16 | +#include "spioutils.hpp" | ||
17 | + | ||
18 | +void SP_IOUtils :: inetNtoa( in_addr * addr, char * ip, int size ) | ||
19 | +{ | ||
20 | +#if defined (linux) || defined (__sgi) || defined (__hpux) \ | ||
21 | + || defined (__FreeBSD__) || defined (__APPLE__) | ||
22 | + const unsigned char *p = ( const unsigned char *) addr; | ||
23 | + snprintf( ip, size, "%i.%i.%i.%i", p[0], p[1], p[2], p[3] ); | ||
24 | +#else | ||
25 | + snprintf( ip, size, "%i.%i.%i.%i", addr->s_net, addr->s_host, addr->s_lh, addr->s_impno ); | ||
26 | +#endif | ||
27 | +} | ||
28 | + | ||
29 | +int SP_IOUtils :: setNonblock( int fd ) | ||
30 | +{ | ||
31 | +#ifdef WIN32 | ||
32 | + unsigned long nonblocking = 1; | ||
33 | + ioctlsocket( fd, FIONBIO, (unsigned long*) &nonblocking ); | ||
34 | +#else | ||
35 | + int flags; | ||
36 | + | ||
37 | + flags = fcntl( fd, F_GETFL ); | ||
38 | + if( flags < 0 ) return flags; | ||
39 | + | ||
40 | + flags |= O_NONBLOCK; | ||
41 | + if( fcntl( fd, F_SETFL, flags ) < 0 ) return -1; | ||
42 | +#endif | ||
43 | + | ||
44 | + return 0; | ||
45 | +} | ||
46 | + | ||
47 | +int SP_IOUtils :: setBlock( int fd ) | ||
48 | +{ | ||
49 | +#ifdef WIN32 | ||
50 | + | ||
51 | + unsigned long nonblocking = 0; | ||
52 | + ioctlsocket( fd, FIONBIO, (unsigned long*) &nonblocking ); | ||
53 | + | ||
54 | +#else | ||
55 | + | ||
56 | + int flags; | ||
57 | + | ||
58 | + flags = fcntl( fd, F_GETFL ); | ||
59 | + if( flags < 0 ) return flags; | ||
60 | + | ||
61 | + flags &= ~O_NONBLOCK; | ||
62 | + if( fcntl( fd, F_SETFL, flags ) < 0 ) return -1; | ||
63 | +#endif | ||
64 | + | ||
65 | + return 0; | ||
66 | +} | ||
67 | + | ||
68 | +int SP_IOUtils :: tcpListen( const char * ip, int port, int * fd, int blocking ) | ||
69 | +{ | ||
70 | + int ret = 0; | ||
71 | + | ||
72 | + int listenFd = socket( AF_INET, SOCK_STREAM, 0 ); | ||
73 | + if( listenFd < 0 ) { | ||
74 | + sp_syslog( LOG_WARNING, "socket failed, errno %d, %s", errno, strerror( errno ) ); | ||
75 | + ret = -1; | ||
76 | + } | ||
77 | + | ||
78 | + if( 0 == ret && 0 == blocking ) { | ||
79 | + if( setNonblock( listenFd ) < 0 ) { | ||
80 | + sp_syslog( LOG_WARNING, "failed to set socket to non-blocking" ); | ||
81 | + ret = -1; | ||
82 | + } | ||
83 | + } | ||
84 | + | ||
85 | + if( 0 == ret ) { | ||
86 | + int flags = 1; | ||
87 | + if( setsockopt( listenFd, SOL_SOCKET, SO_REUSEADDR, (char*)&flags, sizeof( flags ) ) < 0 ) { | ||
88 | + sp_syslog( LOG_WARNING, "failed to set setsock to reuseaddr" ); | ||
89 | + ret = -1; | ||
90 | + } | ||
91 | + if( setsockopt( listenFd, IPPROTO_TCP, TCP_NODELAY, (char*)&flags, sizeof(flags) ) < 0 ) { | ||
92 | + sp_syslog( LOG_WARNING, "failed to set socket to nodelay" ); | ||
93 | + ret = -1; | ||
94 | + } | ||
95 | + } | ||
96 | + | ||
97 | + struct sockaddr_in addr; | ||
98 | + | ||
99 | + if( 0 == ret ) { | ||
100 | + memset( &addr, 0, sizeof( addr ) ); | ||
101 | + addr.sin_family = AF_INET; | ||
102 | + addr.sin_port = htons( port ); | ||
103 | + | ||
104 | + addr.sin_addr.s_addr = INADDR_ANY; | ||
105 | + if( '\0' != *ip ) { | ||
106 | + if( 0 == sp_inet_aton( ip, &addr.sin_addr ) ) { | ||
107 | + sp_syslog( LOG_WARNING, "failed to convert %s to inet_addr", ip ); | ||
108 | + ret = -1; | ||
109 | + } | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + if( 0 == ret ) { | ||
114 | + if( bind( listenFd, (struct sockaddr*)&addr, sizeof( addr ) ) < 0 ) { | ||
115 | + sp_syslog( LOG_WARNING, "bind failed, errno %d, %s", errno, strerror( errno ) ); | ||
116 | + ret = -1; | ||
117 | + } | ||
118 | + } | ||
119 | + | ||
120 | + if( 0 == ret ) { | ||
121 | + if( ::listen( listenFd, 1024 ) < 0 ) { | ||
122 | + sp_syslog( LOG_WARNING, "listen failed, errno %d, %s", errno, strerror( errno ) ); | ||
123 | + ret = -1; | ||
124 | + } | ||
125 | + } | ||
126 | + | ||
127 | + if( 0 != ret && listenFd >= 0 ) sp_close( listenFd ); | ||
128 | + | ||
129 | + if( 0 == ret ) { | ||
130 | + * fd = listenFd; | ||
131 | + sp_syslog( LOG_NOTICE, "Listen on port [%d]", port ); | ||
132 | + } | ||
133 | + | ||
134 | + return ret; | ||
135 | +} | ||
136 | + | ||
137 | +int SP_IOUtils :: tcpListen( const char * path, int * fd, int blocking, int mode ) | ||
138 | +{ | ||
139 | + int ret = 0; | ||
140 | + | ||
141 | +#ifndef WIN32 | ||
142 | + | ||
143 | + struct sockaddr_un addr; | ||
144 | + memset( &addr, 0, sizeof( addr ) ); | ||
145 | + | ||
146 | + if( strlen( path ) > ( sizeof( addr.sun_path ) - 1 ) ) { | ||
147 | + sp_syslog( LOG_WARNING, "UNIX socket name %s too long", path ); | ||
148 | + return -1; | ||
149 | + } | ||
150 | + | ||
151 | + if( 0 == access( path, F_OK ) ) { | ||
152 | + if( 0 != unlink( path ) ) { | ||
153 | + sp_syslog( LOG_WARNING, "unlink %s failed, errno %d, %s", | ||
154 | + path, errno, strerror( errno ) ); | ||
155 | + return -1; | ||
156 | + } | ||
157 | + } | ||
158 | + | ||
159 | + addr.sun_family = AF_UNIX; | ||
160 | + strncpy( addr.sun_path, path, sizeof( addr.sun_path ) - 1 ); | ||
161 | + | ||
162 | + int listenFd = socket( AF_UNIX, SOCK_STREAM, 0 ); | ||
163 | + if( listenFd < 0 ) { | ||
164 | + sp_syslog( LOG_WARNING, "listen failed, errno %d, %s", errno, strerror( errno ) ); | ||
165 | + ret = -1; | ||
166 | + } | ||
167 | + | ||
168 | + if( 0 == ret && 0 == blocking ) { | ||
169 | + if( setNonblock( listenFd ) < 0 ) { | ||
170 | + sp_syslog( LOG_WARNING, "failed to set socket to non-blocking" ); | ||
171 | + ret = -1; | ||
172 | + } | ||
173 | + } | ||
174 | + | ||
175 | + if( 0 == ret ) { | ||
176 | + int flags = 1; | ||
177 | + if( setsockopt( listenFd, SOL_SOCKET, SO_REUSEADDR, (char*)&flags, sizeof( flags ) ) < 0 ) { | ||
178 | + sp_syslog( LOG_WARNING, "failed to set setsock to reuseaddr" ); | ||
179 | + ret = -1; | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
183 | + if( 0 == ret ) { | ||
184 | + if( bind( listenFd, (struct sockaddr*)&addr, sizeof( addr ) ) < 0 ) { | ||
185 | + sp_syslog( LOG_WARNING, "bind failed, errno %d, %s", errno, strerror( errno ) ); | ||
186 | + ret = -1; | ||
187 | + } | ||
188 | + } | ||
189 | + | ||
190 | + if( 0 == ret ) { | ||
191 | + if( ::listen( listenFd, 1024 ) < 0 ) { | ||
192 | + sp_syslog( LOG_WARNING, "listen failed, errno %d, %s", errno, strerror( errno ) ); | ||
193 | + ret = -1; | ||
194 | + } | ||
195 | + } | ||
196 | + | ||
197 | + if( 0 != ret && listenFd >= 0 ) sp_close( listenFd ); | ||
198 | + | ||
199 | + if( 0 == ret ) { | ||
200 | + * fd = listenFd; | ||
201 | + | ||
202 | + if( mode > 0 ) { | ||
203 | + if( 0 != fchmod( *fd, (mode_t)mode ) ) { | ||
204 | + sp_syslog( LOG_WARNING, "fchmod fail, errno %d, %s", errno, strerror( errno ) ); | ||
205 | + } | ||
206 | + } | ||
207 | + | ||
208 | + sp_syslog( LOG_NOTICE, "Listen on [%s]", path ); | ||
209 | + } | ||
210 | + | ||
211 | +#endif | ||
212 | + | ||
213 | + return ret; | ||
214 | +} | ||
215 | + | ||
216 | +int SP_IOUtils :: initDaemon( const char * workdir ) | ||
217 | +{ | ||
218 | +#ifndef WIN32 | ||
219 | + | ||
220 | + int i; | ||
221 | + pid_t pid; | ||
222 | + | ||
223 | + if ( (pid = fork()) < 0) | ||
224 | + return (-1); | ||
225 | + else if (pid) | ||
226 | + _exit(0); /* parent terminates */ | ||
227 | + | ||
228 | + /* child 1 continues... */ | ||
229 | + | ||
230 | + if (setsid() < 0) /* become session leader */ | ||
231 | + return (-1); | ||
232 | + | ||
233 | + assert( signal( SIGHUP, SIG_IGN ) != SIG_ERR ); | ||
234 | + assert( signal( SIGPIPE, SIG_IGN ) != SIG_ERR ); | ||
235 | + assert( signal( SIGALRM, SIG_IGN ) != SIG_ERR ); | ||
236 | + assert( signal( SIGCHLD, SIG_IGN ) != SIG_ERR ); | ||
237 | + | ||
238 | + if ( (pid = fork()) < 0) | ||
239 | + return (-1); | ||
240 | + else if (pid) | ||
241 | + _exit(0); /* child 1 terminates */ | ||
242 | + | ||
243 | + /* child 2 continues... */ | ||
244 | + | ||
245 | + if( NULL != workdir ) chdir( workdir ); /* change working directory */ | ||
246 | + | ||
247 | + /* close off file descriptors */ | ||
248 | + for (i = 0; i < 64; i++) | ||
249 | + close(i); | ||
250 | + | ||
251 | + /* redirect stdin, stdout, and stderr to /dev/null */ | ||
252 | + open("/dev/null", O_RDONLY); | ||
253 | + open("/dev/null", O_RDWR); | ||
254 | + open("/dev/null", O_RDWR); | ||
255 | + | ||
256 | +#endif | ||
257 | + | ||
258 | + return (0); /* success */ | ||
259 | +} | ||
260 | + |
请
注册
或
登录
后发表评论