1
+ /*
2
+ +----------------------------------------------------------------------+
3
+ | Copyright (c) 2009-2013 The PHP Group |
4
+ +----------------------------------------------------------------------+
5
+ | This source file is subject to version 3.01 of the PHP license, |
6
+ | that is bundled with this package in the file LICENSE, and is |
7
+ | available through the world-wide-web at the following url: |
8
+ | http://www.php.net/license/3_01.txt. |
9
+ | If you did not receive a copy of the PHP license and are unable to |
10
+ | obtain it through the world-wide-web, please send a note to |
11
+ | [email protected] so we can mail you a copy immediately. |
12
+ +----------------------------------------------------------------------+
13
+ | Authors: Mikko Koppanen <[email protected] > |
14
+ +----------------------------------------------------------------------+
15
+ */
16
+
17
+ #ifdef HAVE_CONFIG_H
18
+ #include "config.h"
19
+ #endif
20
+
21
+ #include <php.h>
22
+ #include "php_libmemcached_compat.h"
23
+ #include <libmemcachedprotocol-0.0/handler.h>
24
+
25
+ #include "php_memcached.h"
26
+ #include "php_memcached_server.h"
27
+
28
+ #include <event2/listener.h>
29
+
30
+ #undef NDEBUG
31
+ #undef _NDEBUG
32
+ #include <assert.h>
33
+
34
+
35
+ struct _php_memc_proto_handler_t {
36
+ memcached_binary_protocol_callback_st callbacks ;
37
+ struct memcached_protocol_st * protocol_handle ;
38
+ struct event_base * event_base ;
39
+ };
40
+
41
+ // memcached protocol callbacks
42
+ static
43
+ protocol_binary_response_status s_add_handler (const void * cookie , const void * key , uint16_t keylen , const void * data ,
44
+ uint32_t datalen , uint32_t flags , uint32_t exptime , uint64_t * cas )
45
+ {
46
+ protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_SUCCESS ;
47
+
48
+ fprintf (stderr , "adding key\n" );
49
+
50
+ return retval ;
51
+ }
52
+
53
+ // libevent callbacks
54
+ typedef struct _php_memc_client_t {
55
+ struct memcached_protocol_client_st * protocol_client ;
56
+ struct event_base * event_base ;
57
+ } php_memc_client_t ;
58
+
59
+ static
60
+ void s_handle_memcached_event (evutil_socket_t fd , short what , void * arg )
61
+ {
62
+ int rc ;
63
+ short flags = 0 ;
64
+ php_memc_client_t * client = (php_memc_client_t * )arg ;
65
+ memcached_protocol_event_t events = memcached_protocol_client_work (client -> protocol_client );
66
+
67
+ if (events & MEMCACHED_PROTOCOL_ERROR_EVENT ) {
68
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Client error during communication" );
69
+
70
+ memcached_protocol_client_destroy (client -> protocol_client );
71
+ efree (client );
72
+ evutil_closesocket (fd );
73
+ return ;
74
+ }
75
+
76
+ if (events & MEMCACHED_PROTOCOL_WRITE_EVENT ) {
77
+ flags = EV_WRITE ;
78
+ }
79
+
80
+ if (events & MEMCACHED_PROTOCOL_READ_EVENT ) {
81
+ flags |= EV_READ ;
82
+ }
83
+
84
+ rc = event_base_once (client -> event_base , fd , flags , s_handle_memcached_event , client , NULL );
85
+ if (rc != 0 ) {
86
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Failed to schedule events" );
87
+ }
88
+ }
89
+
90
+ static
91
+ void s_accept_cb (evutil_socket_t fd , short what , void * arg )
92
+ {
93
+ int rc ;
94
+ php_memc_client_t * client ;
95
+ struct sockaddr_storage addr ;
96
+ socklen_t addr_len ;
97
+ evutil_socket_t sock ;
98
+
99
+ php_memc_proto_handler_t * handler = (php_memc_proto_handler_t * ) arg ;
100
+
101
+ /* Accept the connection */
102
+ addr_len = sizeof (addr );
103
+ sock = accept (fd , (struct sockaddr * ) & addr , & addr_len );
104
+
105
+ if (sock == -1 ) {
106
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Failed to accept the client: %s" , strerror (errno ));
107
+ return ;
108
+ }
109
+
110
+ client = ecalloc (1 , sizeof (php_memc_client_t ));
111
+ client -> protocol_client = memcached_protocol_create_client (handler -> protocol_handle , sock );
112
+ client -> event_base = handler -> event_base ;
113
+
114
+ if (!client -> protocol_client ) {
115
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Failed to allocate protocol client" );
116
+ efree (client );
117
+ evutil_closesocket (sock );
118
+ return ;
119
+ }
120
+
121
+ // TODO: this should timeout
122
+ rc = event_base_once (handler -> event_base , sock , EV_READ , s_handle_memcached_event , client , NULL );
123
+
124
+ if (rc != 0 ) {
125
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Failed to add event for client" );
126
+ memcached_protocol_client_destroy (client -> protocol_client );
127
+ efree (client );
128
+ evutil_closesocket (sock );
129
+ return ;
130
+ }
131
+ }
132
+
133
+ php_memc_proto_handler_t * php_memc_proto_handler_new ()
134
+ {
135
+ php_memc_proto_handler_t * handler = ecalloc (1 , sizeof (php_memc_proto_handler_t ));
136
+
137
+ handler -> protocol_handle = memcached_protocol_create_instance ();
138
+ assert (handler -> protocol_handle );
139
+
140
+ memset (& handler -> callbacks , 0 , sizeof (memcached_binary_protocol_callback_st ));
141
+
142
+ handler -> callbacks .interface_version = MEMCACHED_PROTOCOL_HANDLER_V1 ;
143
+ handler -> callbacks .interface .v1 .add = s_add_handler ;
144
+ /*handler->callbacks.interface.v1.append = s_append_handler;
145
+ handler->callbacks.interface.v1.decrement = s_decrement_handler;
146
+ handler->callbacks.interface.v1.delete_object = s_delete_handler;
147
+ handler->callbacks.interface.v1.flush_object = s_flush_handler;
148
+ handler->callbacks.interface.v1.get = s_get_handler;
149
+ handler->callbacks.interface.v1.increment = s_increment_handler;
150
+ handler->callbacks.interface.v1.noop = s_noop_handler;
151
+ handler->callbacks.interface.v1.prepend = s_prepend_handler;
152
+ handler->callbacks.interface.v1.quit = s_quit_handler;
153
+ handler->callbacks.interface.v1.replace = s_replace_handler;
154
+ handler->callbacks.interface.v1.set = s_set_handler;
155
+ handler->callbacks.interface.v1.stat = s_stat_handler;
156
+ handler->callbacks.interface.v1.version = s_version_handler;
157
+ */
158
+
159
+ memcached_binary_protocol_set_callbacks (handler -> protocol_handle , & handler -> callbacks );
160
+ return handler ;
161
+ }
162
+
163
+ static
164
+ evutil_socket_t s_create_listening_socket (const char * spec )
165
+ {
166
+ evutil_socket_t sock ;
167
+ struct sockaddr_storage addr ;
168
+ int addr_len ;
169
+
170
+ int rc ;
171
+
172
+ addr_len = sizeof (struct sockaddr );
173
+ rc = evutil_parse_sockaddr_port (spec , (struct sockaddr * ) & addr , & addr_len );
174
+ assert (rc == 0 );
175
+
176
+ sock = socket (AF_INET , SOCK_STREAM , 0 );
177
+ assert (sock >= 0 );
178
+
179
+ rc = bind (sock , (struct sockaddr * ) & addr , addr_len );
180
+ assert (sock >= 0 );
181
+
182
+ rc = listen (sock , 1024 );
183
+ assert (rc >= 0 );
184
+
185
+ rc = evutil_make_socket_nonblocking (sock );
186
+ assert (rc == 0 );
187
+
188
+ rc = evutil_make_listen_socket_reuseable (sock );
189
+ assert (rc == 0 );
190
+
191
+ rc = evutil_make_socket_closeonexec (sock );
192
+ assert (rc == 0 );
193
+
194
+ return sock ;
195
+ }
196
+
197
+ void my_run (php_memc_proto_handler_t * handler )
198
+ {
199
+ struct event * accept_event ;
200
+ evutil_socket_t sock = s_create_listening_socket ("127.0.0.1:3434" );
201
+
202
+ handler -> event_base = event_base_new ();
203
+
204
+ accept_event = event_new (handler -> event_base , sock , EV_READ | EV_PERSIST , s_accept_cb , handler );
205
+ event_add (accept_event , NULL );
206
+
207
+ int f = event_base_dispatch (handler -> event_base );
208
+ fprintf (stderr , "Re: %d\n" , f );
209
+ }
210
+
211
+ void php_memc_proto_handler_destroy (php_memc_proto_handler_t * * ptr )
212
+ {
213
+ php_memc_proto_handler_t * handler = * ptr ;
214
+
215
+ if (handler -> protocol_handle )
216
+ memcached_protocol_destroy_instance (handler -> protocol_handle );
217
+
218
+ efree (handler );
219
+ * ptr = NULL ;
220
+ }
0 commit comments