+
+struct connection
+{
+ void *userdata;
+ struct event event;
+};
+
+/* The default maximum number of connections... (change with -c) */
+static int maxconns = 1024;
+
+static struct connection *socket_userdata_map;
+static bool verbose= false;
+static struct event_base *event_base;
+
+struct options_st {
+ char *pid_file;
+ bool has_port;
+ in_port_t port;
+} global_options;
+
+typedef struct options_st options_st;
+
+/**
+ * Callback for driving a client connection
+ * @param fd the socket for the client socket
+ * @param which identifying the event that occurred (not used)
+ * @param arg the connection structure for the client
+ */
+static void drive_client(memcached_socket_t fd, short which, void *arg)
+{
+ (void)which;
+ struct connection *client= arg;
+ struct memcached_protocol_client_st* c= client->userdata;
+ assert(c != NULL);
+
+ memcached_protocol_event_t events= memcached_protocol_client_work(c);
+ if (events & MEMCACHED_PROTOCOL_ERROR_EVENT)
+ {
+ memcached_protocol_client_destroy(c);
+ closesocket(fd);
+ } else {
+ short flags = 0;
+ if (events & MEMCACHED_PROTOCOL_WRITE_EVENT)
+ {
+ flags= EV_WRITE;
+ }
+
+ if (events & MEMCACHED_PROTOCOL_READ_EVENT)
+ {
+ flags|= EV_READ;
+ }
+
+ event_set(&client->event, (intptr_t)fd, flags, drive_client, client);
+ event_base_set(event_base, &client->event);
+
+ if (event_add(&client->event, 0) == -1)
+ {
+ (void)fprintf(stderr, "Failed to add event for %d\n", fd);
+ memcached_protocol_client_destroy(c);
+ closesocket(fd);
+ }
+ }
+}
+
+/**
+ * Callback for accepting new connections
+ * @param fd the socket for the server socket
+ * @param which identifying the event that occurred (not used)
+ * @param arg the connection structure for the server
+ */
+static void accept_handler(memcached_socket_t fd, short which, void *arg)
+{
+ (void)which;
+ struct connection *server= arg;
+ /* accept new client */
+ struct sockaddr_storage addr;
+ socklen_t addrlen= sizeof(addr);
+ memcached_socket_t sock= accept(fd, (struct sockaddr *)&addr, &addrlen);
+
+ if (sock == INVALID_SOCKET)
+ {
+ perror("Failed to accept client");
+ return ;
+ }
+
+#ifndef WIN32
+ if (sock >= maxconns)
+ {
+ (void)fprintf(stderr, "Client outside socket range (specified with -c)\n");
+ closesocket(sock);
+ return ;
+ }
+#endif
+
+ struct memcached_protocol_client_st* c;
+ c= memcached_protocol_create_client(server->userdata, sock);
+ if (c == NULL)
+ {
+ (void)fprintf(stderr, "Failed to create client\n");
+ closesocket(sock);
+ }
+ else
+ {
+ struct connection *client = &socket_userdata_map[sock];
+ client->userdata= c;
+
+ event_set(&client->event, (intptr_t)sock, EV_READ, drive_client, client);
+ event_base_set(event_base, &client->event);
+ if (event_add(&client->event, 0) == -1)
+ {
+ (void)fprintf(stderr, "Failed to add event for %d\n", sock);
+ memcached_protocol_client_destroy(c);
+ closesocket(sock);
+ }
+ }
+}