diff options
author | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-07 19:58:23 +0000 |
---|---|---|
committer | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-07 19:58:23 +0000 |
commit | cb3b1f93130040a150e7fcc57cd4d5a75569685a (patch) | |
tree | ff93665e3c1478c61663d1107cd42dc25b31448d /remoting/tools | |
parent | b0110e822ac2b2db56d1b1542aad06da573cd544 (diff) | |
download | chromium_src-cb3b1f93130040a150e7fcc57cd4d5a75569685a.zip chromium_src-cb3b1f93130040a150e7fcc57cd4d5a75569685a.tar.gz chromium_src-cb3b1f93130040a150e7fcc57cd4d5a75569685a.tar.bz2 |
Copy the (early prototype of) remoting in Chrome into the public tree.
At the moment, this is a semi-functional demo.
BUG=none
TEST=build/run all unittests on linux
Review URL: http://codereview.chromium.org/2690003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49087 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/tools')
-rw-r--r-- | remoting/tools/client_webserver/main.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/remoting/tools/client_webserver/main.c b/remoting/tools/client_webserver/main.c new file mode 100644 index 0000000..1182ab0 --- /dev/null +++ b/remoting/tools/client_webserver/main.c @@ -0,0 +1,164 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Simple webserver that returns empty content with the requested mimetype. +// +// For example: +// http://localhost:8080/pepper-application/x-chromoting-plugin +// Will return empty content, but with the requested mimetype: +// Content-Type: pepper-application/x-chromoting-plugin +// +// This is useful for testing the Chromoting plugin while we wait for +// updated mimetype support to be added to Chrome. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/wait.h> +#include <netinet/in.h> + +#define PORT 8080 + +void error(const char *msg) { + fprintf(stderr, "ERROR - %s\n", msg); + exit(1); +} + +// Read text data from a socket to a buffer. +// Data up to the next \n char is read into the buffer. +void read_text_data(int sock, char *buffer, int buffsize) { + int num_bytes; + *buffer = '\0'; + + for (num_bytes = 1; num_bytes < buffsize-1; num_bytes++) { + char ch; + + int num_bytes_read = read(sock, &ch, 1); + if (num_bytes_read == 1) { + if (ch == '\n') { + break; + } + *buffer++ = ch; + } else if (num_bytes_read == 0) { + break; + } else { + error("read_text_data failed"); + } + } + *buffer++ = '\0'; +} + +// Write data from a null-terminated buffer to a socket. +void write_data(int sock, const char *buffer) { + int num_bytes = strlen(buffer); + + while (num_bytes > 0) { + int num_bytes_written = write(sock, buffer, num_bytes); + if (num_bytes_written <= 0) { + error("write_data failed"); + } + num_bytes -= num_bytes_written; + buffer += num_bytes_written; + } +} + +void handle_request(int connection) { + printf("Handling request...\n"); + char buffer[512]; + buffer[0] = '\0'; + + // Read the first line of the request. This will be something like: + // GET /index.html HTTP/1.1 + read_text_data(connection, buffer, 512); + + char *saveptr; + char *request = strtok_r(buffer, " ", &saveptr); + char *resource = strtok_r(NULL, " ", &saveptr); + char *version = strtok_r(NULL, " ", &saveptr); + + char mime_type[512]; + strncpy(mime_type, &resource[1], 511); + mime_type[511] = '\0'; + + if (strcmp(request, "GET")) { + printf("Unknown request: 'GET %s %s'\n", request, version); + } else { + printf("Requesting '%s'\n", mime_type); + } + + // Keep reading until we encounter a blank line. + // This will skip over the Host, Connection, User-Agent, ... + char ignore[512] = "ignore"; + while (strspn(ignore, " \n\r\t") != strlen(ignore)) { + read_text_data(connection, ignore, sizeof(ignore)); + } + + // At this point, a normal webserver would verify that the requested + // resource exists and then return it with the appropriate mimetype. + + // However, we return empty content, but with the requested plugin mimetype. + write_data(connection, "HTTP/1.0 200 OK\r\n"); + write_data(connection, "Content-Type: "); + write_data(connection, mime_type); + write_data(connection, "\r\n\r\n"); + + // This dummy data is unused, but must be present or else the reader may hang. + write_data(connection, "Data\n"); +} + +int main(int argc, char *argv[]) { + printf("Chromoting client webserver: http://localhost:%d\n", PORT); + + signal(SIGCHLD, SIG_IGN); + + // Create socket. + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + error("Unable to open socket"); + } + + // Initialize socket address struct. + struct sockaddr_in serv_addr; + bzero((char*)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(PORT); + + // Bind socket. + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + error("Unable to bind socket"); + } + + if (listen(sock, 5) < 0) { + error("Unable to listen to socket"); + } + + while (1) { + int connection = accept(sock, NULL, NULL); + if (connection < 0) { + error("Unable to accept connection"); + } + + pid_t pid = fork(); + if (pid == 0) { + // Child process. + if (close(sock) < 0) { + error("Unable to close socket in child"); + } + + // Handle the request. + handle_request(connection); + + // Success. Exit to kill child process. + exit(0); + } else { + // Parent process. + if (close(connection) < 0) { + error("Unable to close connection in parent"); + } + } + } + + return 0; +} |