Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
a52925d5
Commit
a52925d5
authored
Jan 04, 2012
by
Pieter Noordhuis
Browse files
Initial stab at a new context structure
parent
11ad647a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
a52925d5
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
include
./Makefile.common
include
./Makefile.common
OBJ
=
net.o hiredis.o sds.o async.o parser.o object.o handle.o format.o
OBJ
=
net.o hiredis.o sds.o async.o parser.o object.o handle.o format.o
context.o
BINS
=
hiredis-example hiredis-test
BINS
=
hiredis-example hiredis-test
all
:
$(DYLIBNAME) $(BINS)
all
:
$(DYLIBNAME) $(BINS)
...
...
context.c
0 → 100644
View file @
a52925d5
#include <string.h>
#include <assert.h>
/* local */
#include "context.h"
#include "object.h"
static
void
redis__clear_address
(
redis_context
*
ctx
)
{
memset
(
&
ctx
->
address
,
0
,
sizeof
(
ctx
->
address
));
}
int
redis_context_init
(
redis_context
*
ctx
)
{
int
rv
;
rv
=
redis_handle_init
(
&
ctx
->
handle
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
/* Pull default timeout from handle */
ctx
->
timeout
=
redis_handle_get_timeout
(
&
ctx
->
handle
);
/* Reinitialize parser with bundled object functions */
redis_parser_init
(
&
ctx
->
handle
.
parser
,
&
redis_object_parser_callbacks
);
/* Clear address field */
redis__clear_address
(
ctx
);
return
REDIS_OK
;
}
int
redis_context_destroy
(
redis_context
*
ctx
)
{
int
rv
;
rv
=
redis_handle_destroy
(
&
ctx
->
handle
);
return
rv
;
}
int
redis_context_set_timeout
(
redis_context
*
ctx
,
unsigned
long
timeout
)
{
int
rv
;
rv
=
redis_handle_set_timeout
(
&
ctx
->
handle
,
timeout
);
if
(
rv
==
REDIS_OK
)
{
ctx
->
timeout
=
timeout
;
}
return
rv
;
}
unsigned
long
redis_context_get_timeout
(
redis_context
*
ctx
)
{
return
ctx
->
timeout
;
}
static
int
redis__connect
(
redis_context
*
ctx
)
{
int
rv
;
rv
=
redis_handle_connect_address
(
&
ctx
->
handle
,
&
ctx
->
address
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
rv
=
redis_handle_wait_connected
(
&
ctx
->
handle
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
return
REDIS_OK
;
}
static
int
redis__first_connect
(
redis_context
*
ctx
)
{
int
rv
;
rv
=
redis__connect
(
ctx
);
if
(
rv
!=
REDIS_OK
)
{
redis__clear_address
(
ctx
);
return
rv
;
}
return
REDIS_OK
;
}
int
redis_context_connect_in
(
redis_context
*
ctx
,
struct
sockaddr_in
addr
)
{
ctx
->
address
.
sa_family
=
AF_INET
;
ctx
->
address
.
sa_addrlen
=
sizeof
(
addr
);
ctx
->
address
.
sa_addr
.
in
=
addr
;
return
redis__first_connect
(
ctx
);
}
int
redis_context_connect_in6
(
redis_context
*
ctx
,
struct
sockaddr_in6
addr
)
{
ctx
->
address
.
sa_family
=
AF_INET6
;
ctx
->
address
.
sa_addrlen
=
sizeof
(
addr
);
ctx
->
address
.
sa_addr
.
in6
=
addr
;
return
redis__first_connect
(
ctx
);
}
int
redis_context_connect_un
(
redis_context
*
ctx
,
struct
sockaddr_un
addr
)
{
ctx
->
address
.
sa_family
=
AF_LOCAL
;
ctx
->
address
.
sa_addrlen
=
sizeof
(
addr
);
ctx
->
address
.
sa_addr
.
un
=
addr
;
return
redis__first_connect
(
ctx
);
}
int
redis_context_connect_gai
(
redis_context
*
ctx
,
const
char
*
host
,
int
port
)
{
redis_address
address
;
int
rv
;
rv
=
redis_handle_connect_gai
(
&
ctx
->
handle
,
AF_INET
,
host
,
port
,
&
address
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
rv
=
redis_handle_wait_connected
(
&
ctx
->
handle
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
/* Store address that getaddrinfo resolved and we are now connected to */
ctx
->
address
=
address
;
return
REDIS_OK
;
}
context.h
0 → 100644
View file @
a52925d5
#ifndef _HIREDIS_CONTEXT_H
#define _HIREDIS_CONTEXT_H 1
/* local */
#include "handle.h"
typedef
struct
redis_context_s
redis_context
;
struct
redis_context_s
{
redis_handle
handle
;
unsigned
long
timeout
;
/* private: used to reconnect */
redis_address
address
;
};
int
redis_context_init
(
redis_context
*
ctx
);
int
redis_context_destroy
(
redis_context
*
ctx
);
int
redis_context_set_timeout
(
redis_context
*
,
unsigned
long
us
);
unsigned
long
redis_handle_get_timeout
(
redis_handle
*
);
int
redis_context_connect_in
(
redis_context
*
,
struct
sockaddr_in
addr
);
int
redis_context_connect_in6
(
redis_context
*
,
struct
sockaddr_in6
addr
);
int
redis_context_connect_un
(
redis_context
*
,
struct
sockaddr_un
addr
);
int
redis_context_connect_gai
(
redis_context
*
,
const
char
*
addr
,
int
port
);
#endif
test/Makefile
View file @
a52925d5
include
../Makefile.common
include
../Makefile.common
TESTS
=
test-format test-parser test-object test-handle
TESTS
=
test-format test-parser test-object test-handle
test-context
all
:
$(TESTS)
all
:
$(TESTS)
...
...
test/test-context.c
0 → 100644
View file @
a52925d5
#include "../fmacros.h"
/* misc */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
/* inet_pton */
#include <arpa/inet.h>
/* getaddrinfo */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
/* local */
#include "../context.h"
#include "test-helper.h"
#define SETUP_CONNECT() \
redis_context c; \
int rv; \
rv = redis_context_init(&c); \
assert(rv == REDIS_OK); \
rv = redis_context_set_timeout(&c, 10000); \
assert(rv == REDIS_OK);
TEST
(
connect_in_refused
)
{
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
()
+
1
);
assert
(
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
sa
.
sin_addr
)
==
1
);
rv
=
redis_context_connect_in
(
&
c
,
sa
);
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ECONNREFUSED
);
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_in6_refused
)
{
SETUP_CONNECT
();
struct
sockaddr_in6
sa
;
sa
.
sin6_family
=
AF_INET6
;
sa
.
sin6_port
=
htons
(
redis_port
()
+
1
);
assert
(
inet_pton
(
AF_INET6
,
"::1"
,
&
sa
.
sin6_addr
)
==
1
);
rv
=
redis_context_connect_in6
(
&
c
,
sa
);
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ECONNREFUSED
);
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_un_noent
)
{
SETUP_CONNECT
();
struct
sockaddr_un
sa
;
sa
.
sun_family
=
AF_LOCAL
;
strcpy
((
char
*
)
&
sa
.
sun_path
,
"/tmp/idontexist.sock"
);
rv
=
redis_context_connect_un
(
&
c
,
sa
);
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ENOENT
);
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_timeout
)
{
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
());
assert
(
inet_pton
(
AF_INET
,
"10.255.255.254"
,
&
sa
.
sin_addr
)
==
1
);
long
long
t1
,
t2
;
t1
=
usec
();
rv
=
redis_context_connect_in
(
&
c
,
sa
);
t2
=
usec
();
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ETIMEDOUT
);
assert
((
t2
-
t1
)
<
15000
);
/* 5ms of slack should be enough */
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_success
)
{
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
());
assert
(
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
sa
.
sin_addr
)
==
1
);
rv
=
redis_context_connect_in
(
&
c
,
sa
);
assert_equal_int
(
rv
,
REDIS_OK
);
/* Address should be set when connection was made */
assert_equal_int
(
c
.
address
.
sa_family
,
AF_INET
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_gai_unknown_host
)
{
SETUP_CONNECT
();
rv
=
redis_context_connect_gai
(
&
c
,
"idontexist.foo"
,
redis_port
());
assert_equal_int
(
rv
,
REDIS_EGAI
);
/* Don't care about the specific error for now. */
assert
(
1
);
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_gai_timeout
)
{
SETUP_CONNECT
();
long
long
t1
,
t2
;
t1
=
usec
();
rv
=
redis_context_connect_gai
(
&
c
,
"10.255.255.254"
,
redis_port
());
t2
=
usec
();
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ETIMEDOUT
);
assert
((
t2
-
t1
)
<
15000
);
/* 5ms of slack should be enough */
/* Address shouldn't be set when no connection could be made */
assert_equal_int
(
c
.
address
.
sa_family
,
0
);
redis_context_destroy
(
&
c
);
}
TEST
(
connect_gai_success
)
{
SETUP_CONNECT
();
rv
=
redis_context_connect_gai
(
&
c
,
"localhost"
,
redis_port
());
assert_equal_int
(
rv
,
REDIS_OK
);
/* Address should be set when connection was made */
assert_equal_int
(
c
.
address
.
sa_family
,
AF_INET
);
redis_context_destroy
(
&
c
);
}
int
main
(
void
)
{
test_connect_in_refused
();
test_connect_in6_refused
();
test_connect_un_noent
();
test_connect_timeout
();
test_connect_success
();
test_connect_gai_unknown_host
();
test_connect_gai_timeout
();
test_connect_gai_success
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment