Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firebase: Merge from master. #53

Merged
merged 7 commits into from
Jan 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion contrib/endpoints/src/api_manager/context/service_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const double kDefaultTraceSampleQps = 0.1;
// The time window to send intermediate report for Grpc streaming (second).
// Default to 10s.
const int kIntermediateReportInterval = 10;

const char kHTTPHeadMethod[] = "HEAD";
const char kHTTPGetMethod[] = "GET";
}

ServiceContext::ServiceContext(std::unique_ptr<ApiManagerEnvInterface> env,
Expand Down Expand Up @@ -74,7 +77,15 @@ MethodCallInfo ServiceContext::GetMethodCallInfo(
if (config_ == nullptr) {
return MethodCallInfo();
}
return config_->GetMethodCallInfo(http_method, url, query_params);
MethodCallInfo method_call_info =
config_->GetMethodCallInfo(http_method, url, query_params);
// HEAD should be treated as GET unless it is specified from service_config.
if (method_call_info.method_info == nullptr &&
http_method == kHTTPHeadMethod) {
method_call_info =
config_->GetMethodCallInfo(kHTTPGetMethod, url, query_params);
}
return method_call_info;
}

const std::string& ServiceContext::project_id() const {
Expand Down
6 changes: 6 additions & 0 deletions contrib/tools/server/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
server:
$(CC) -g -o server server.c

clean:
rm server

25 changes: 25 additions & 0 deletions contrib/tools/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Sample TCP Server

This is a simple TCP server that listens on the specified port (3490 by default) and replies to incoming connections by providing info about src/destination ip/port.

It demonstrates the use of the getsockopt() system call with the ORIGINAL_DST option to retrieve the original destination ip/port after an iptables redirect.

So, for example, if you have the server listening on port 3490 on the local machine and an iptables rule like:

```
iptables -t nat -I OUTPUT 1 -p tcp --dport 4000:5000 -j REDIRECT --to-port 3490
```
your will see:

```
$ telnet localhost 3490
FROM 127.0.0.1:44978, TO 127.0.0.1:3490, ORIG DEST 127.0.0.1:3490

$ telnet localhost 4100
FROM 127.0.0.1:35476, TO 127.0.0.1:3490, ORIG DEST 127.0.0.1:4100

$ telnet 1.1.1.1 5000
FROM 100.100.100.100:60275, TO 127.0.0.1:3490, ORIG DEST 1.1.1.1:5000
```


169 changes: 169 additions & 0 deletions contrib/tools/server/server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
** server.c
* Demo server to check that we can extract all parameters from an incoming
*request
* and respond to it
*/

#include <arpa/inet.h>
#include <errno.h>
#include <linux/netfilter_ipv4.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define DEFAULT_PORT \
"3490" // the port users will be connecting to, if not specified on command
// line

#define QUEUE_SIZE 10 // pending connections queue size

void sigchld_handler(int s) {
int saved_errno = errno;

while (waitpid(-1, NULL, WNOHANG) > 0)
;

errno = saved_errno;
}

int main(int argc, char *argv[]) {
struct sigaction sa;
const int yes = 1;
char *port = DEFAULT_PORT;
int rv;

if (argc > 1) {
port = argv[1];
}

struct addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP

struct addrinfo *server_info = NULL;
if ((rv = getaddrinfo(NULL, port, &hints, &server_info)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}

struct addrinfo *p;
int sockfd; // listen on sock_fd
for (p = server_info; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}

if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}

break;
}

freeaddrinfo(server_info);

if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, QUEUE_SIZE) == -1) {
perror("listen");
exit(1);
}

sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}

char bind_addr_str[INET6_ADDRSTRLEN] = {0};
struct sockaddr_in *bind_sock_addr = (struct sockaddr_in *)p->ai_addr;
inet_ntop(p->ai_family, &bind_sock_addr->sin_addr, bind_addr_str,
p->ai_addrlen);
printf("server %s: waiting for connections on port %s:%u...\n", port,
bind_addr_str, ntohs(bind_sock_addr->sin_port));

while (1) {
socklen_t addr_len = sizeof(struct sockaddr_storage);
int addr_str_len = INET6_ADDRSTRLEN;

struct sockaddr_storage their_addr = {
0}; // connector's address information
int accepted_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_len);
if (accepted_fd == -1) {
perror("accept");
continue;
}

struct sockaddr_in *src_sock_addr = (struct sockaddr_in *)&their_addr;
char their_addr_str[INET6_ADDRSTRLEN] = {0};
inet_ntop(their_addr.ss_family, &src_sock_addr->sin_addr, their_addr_str,
addr_str_len);
printf("server %s: got connection FROM %s:%u\n", port, their_addr_str,
ntohs(src_sock_addr->sin_port));

struct sockaddr_storage my_addr = {0}; // my address information
struct sockaddr_in *dst_sock_addr = (struct sockaddr_in *)&my_addr;
char my_addr_str[INET6_ADDRSTRLEN] = {0};
getsockname(accepted_fd, (struct sockaddr *)dst_sock_addr, &addr_len);
inet_ntop(my_addr.ss_family, &dst_sock_addr->sin_addr, my_addr_str,
addr_str_len);
printf("server %s: got connection TO %s:%u\n", port, my_addr_str,
ntohs(dst_sock_addr->sin_port));

struct sockaddr_storage orig_addr = {0}; // orig address information
struct sockaddr_in *orig_sock_addr = (struct sockaddr_in *)&orig_addr;
char orig_addr_str[INET6_ADDRSTRLEN] = {0};
int status = getsockopt(accepted_fd, SOL_IP, SO_ORIGINAL_DST,
orig_sock_addr, &addr_len);

if (status == 0) {
inet_ntop(orig_addr.ss_family, &orig_sock_addr->sin_addr, orig_addr_str,
addr_str_len);
printf("server %s: ORIG DEST %s:%u\n", port, orig_addr_str,
ntohs(orig_sock_addr->sin_port));
} else {
printf("Could not get orig destination from accepted socket.\n");
}

if (!fork()) { // this is the child process

close(sockfd);
char msg[256] = {0};
snprintf(msg, 256, "FROM %s:%u, TO %s:%u, ORIG DEST %s:%u\n",
their_addr_str, ntohs(src_sock_addr->sin_port), my_addr_str,
ntohs(dst_sock_addr->sin_port), orig_addr_str,
ntohs(orig_sock_addr->sin_port));

if (send(accepted_fd, msg, strlen(msg), 0) == -1) {
perror("send");
}
close(accepted_fd);
exit(0);
}
close(accepted_fd);
}

return 0;
}
2 changes: 2 additions & 0 deletions src/envoy/prototype/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
################################################################################
#

package(default_visibility = ["//visibility:public"])

cc_binary(
name = "envoy_esp",
srcs = [
Expand Down
13 changes: 13 additions & 0 deletions src/envoy/prototype/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ This Proxy will use Envoy and talk to Mixer server.
go run echo.go
```

* Modify your iptables:

```
sudo iptables -t nat -A OUTPUT -p tcp --dport 9090 -j REDIRECT --to-port 9092
```

Once you are done, you should remove this rule:

```
sudo iptables -t nat -D OUTPUT -p tcp --dport 9090 -j REDIRECT --to-port 9092
```


* Start Envoy proxy, run

```
Expand Down
11 changes: 9 additions & 2 deletions src/envoy/prototype/envoy-esp.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"listeners": [
{
"port": 9092,
"bind_to_port": true,
"use_original_dst": true,
"filters": []
},
{
"port": 9090,
"bind_to_port": false,
"filters": [
{
"type": "read",
Expand All @@ -26,7 +33,7 @@
},
"access_log": [
{
"path": "/tmp/access.envoy"
"path": "/dev/stdout"
}
],
"filters": [
Expand All @@ -50,7 +57,7 @@
}
],
"admin": {
"access_log_path": "/tmp/access.envoy",
"access_log_path": "/dev/stdout",
"port": 9001
},
"cluster_manager": {
Expand Down
2 changes: 1 addition & 1 deletion src/envoy/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,6 @@ cc_test(
native.new_git_repository(
name = "envoy_git",
remote = "https://github.com/lyft/envoy.git",
commit = "6b1336a786ebe56c45a1a349ddf706e0526c1ec1", # 2017-01-03
commit = "c36bb76e304ab4c5584a07303e2953a170888319",
build_file_content = BUILD,
)
21 changes: 7 additions & 14 deletions test/backend/echo/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ import (
"io/ioutil"
"net/http"
"strconv"
"sync"
"time"
)

var (
port = flag.Int("port", 8080, "default http port")

mu sync.Mutex
requests = 0
data = 0
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v %v %v %v\n", r.Method, r.URL, r.Proto, r.RemoteAddr)
for name, headers := range r.Header {
for _, h := range headers {
fmt.Printf("%v: %v\n", name, h)
}
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand All @@ -51,24 +54,14 @@ func handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write(body)

mu.Lock()
requests++
data += len(body)
defer mu.Unlock()
fmt.Printf("Requests Requests: %v Data: %v\n", requests, data)
}

func main() {
flag.Parse()

go func() {
for {
mu.Lock()
fmt.Printf("Requests Requests: %v Data: %v\n", requests, data)
mu.Unlock()
time.Sleep(time.Second)
}
}()

fmt.Printf("Listening on port %v\n", *port)

http.HandleFunc("/", handler)
Expand Down