Panda3D
fake_http_server.cxx
1 // Filename: fake_http_server.cxx
2 // Created by: drose (10Dec02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandabase.h"
16 
17 #include "queuedConnectionManager.h"
18 #include "queuedConnectionListener.h"
19 #include "queuedConnectionReader.h"
20 #include "connectionWriter.h"
21 #include "netAddress.h"
22 #include "connection.h"
23 #include "netDatagram.h"
24 #include "pmap.h"
25 
26 #include <ctype.h>
27 
29 QueuedConnectionReader reader(&cm, 10);
30 ConnectionWriter writer(&cm, 10);
31 
32 class ClientState {
33 public:
34  ClientState(Connection *client);
35  void receive_data(const Datagram &data);
36  void receive_line(string line);
37 
38  Connection *_client;
39  string _received;
40 };
41 
42 ClientState::
43 ClientState(Connection *client) {
44  _client = client;
45 }
46 
47 void ClientState::
48 receive_data(const Datagram &data) {
49  _received += data.get_message();
50  size_t next = 0;
51  size_t newline = _received.find('\n', next);
52  while (newline != string::npos) {
53  size_t last = next;
54  next = newline + 1;
55  if (newline > 0 && _received[newline - 1] == '\r') {
56  newline--;
57  }
58  receive_line(_received.substr(last, newline - last));
59  if (next < _received.size() && _received[next] == '\r') {
60  next++;
61  }
62  newline = _received.find('\n', next);
63  }
64  _received = _received.substr(next);
65 }
66 
67 void ClientState::
68 receive_line(string line) {
69  cerr << "received: " << line << "\n";
70  // trim trailing whitespace.
71  size_t size = line.size();
72  while (size > 0 && isspace(line[size - 1])) {
73  size--;
74  }
75  if (size != line.size()) {
76  line = line.substr(0, size);
77  }
78 
79  /*
80  if (line.empty()) {
81  // Start to honor the request, as if we cared.
82  Datagram dg;
83  dg.append_data("HTTP/1.1 200 OK\r\n");
84  writer.send(dg, _client);
85  // Close the connection!
86  cm.close_connection(_client);
87  }
88  */
89 }
90 
91 
92 int
93 main(int argc, char *argv[]) {
94  if (argc != 2) {
95  nout << "fake_http_server port\n";
96  exit(1);
97  }
98 
99  int port = atoi(argv[1]);
100 
101  PT(Connection) rendezvous = cm.open_TCP_server_rendezvous(port, 5);
102 
103  if (rendezvous.is_null()) {
104  nout << "Cannot grab port " << port << ".\n";
105  exit(1);
106  }
107 
108  nout << "Listening for connections on port " << port << "\n";
109 
110  QueuedConnectionListener listener(&cm, 1);
111  listener.add_connection(rendezvous);
112 
113  typedef pmap< PT(Connection), ClientState > Clients;
114  Clients clients;
115 
116  reader.set_raw_mode(1);
117  writer.set_raw_mode(1);
118 
119  bool shutdown = false;
120  while (!shutdown) {
121  // Check for new clients.
122  while (listener.new_connection_available()) {
123  PT(Connection) rv;
124  NetAddress address;
125  PT(Connection) new_connection;
126  if (listener.get_new_connection(rv, address, new_connection)) {
127  nout << "Got connection from " << address << "\n";
128  reader.add_connection(new_connection);
129  clients.insert(Clients::value_type(new_connection, ClientState(new_connection)));
130  }
131  }
132 
133  // Check for reset clients.
134  while (cm.reset_connection_available()) {
135  PT(Connection) connection;
136  if (cm.get_reset_connection(connection)) {
137  nout << "Lost connection from "
138  << connection->get_address() << "\n";
139  clients.erase(connection);
140  cm.close_connection(connection);
141  }
142  }
143 
144  // Process all available datagrams.
145  while (reader.data_available()) {
146  NetDatagram datagram;
147  if (reader.get_data(datagram)) {
148  PT(Connection) client = datagram.get_connection();
149  Clients::iterator ci = clients.find(client);
150  if (ci == clients.end()) {
151  nout << "Received data from unexpected client " << (void *)client
152  << "\n";
153  } else {
154  ClientState &state = (*ci).second;
155  state.receive_data(datagram);
156  }
157  }
158  }
159  }
160 
161  return (0);
162 }
163 
164 
165 
166 
167 
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
A specific kind of Datagram, especially for sending across or receiving from a network.
Definition: netDatagram.h:43
This flavor of ConnectionManager will queue up all of the reset-connection messages from the Connecti...
bool get_reset_connection(PT(Connection) &connection)
If a previous call to reset_connection_available() returned true, this function will return informati...
bool reset_connection_available() const
Returns true if one of the readers/writers/listeners reported a connection reset recently.
bool new_connection_available()
Returns true if a new connection was recently established; the connection information may then be ret...
This class handles threaded delivery of datagrams to various TCP or UDP sockets.
bool add_connection(Connection *connection)
Adds a new socket to the list of sockets the ConnectionReader will monitor.
This flavor of ConnectionReader will read from its sockets and queue up all of the datagrams read for...
string get_message() const
Returns the datagram&#39;s data as a string.
Definition: datagram.I:431
Represents a single TCP or UDP socket for input or output.
Definition: connection.h:32
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
bool close_connection(const PT(Connection) &connection)
Terminates a UDP or TCP socket previously opened.
bool get_new_connection(PT(Connection) &rendezvous, NetAddress &address, PT(Connection) &new_connection)
If a previous call to new_connection_available() returned true, this function will return information...
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound...
Definition: netAddress.h:27
This flavor of ConnectionListener will queue up all of the TCP connections it established for later d...